<script>
    import { chatAdapter, chatData, selectedMessage, zapsPerMessage } from './lib/store';
    import { onMount } from 'svelte';
    import NostrNote from './NostrNote.svelte';
    import * as animateScroll from "svelte-scrollto";

    let events = [];
    let responseEvents = [];
    let responses = {};
    let profiles = {};

    export let websiteOwnerPubkey;
    export let chatConfiguration;
    let prevChatConfiguration;

    $: {
        if (chatConfiguration !== prevChatConfiguration && $chatAdapter) {
            $chatAdapter.setChatConfiguration(
                chatConfiguration.chatType,
                chatConfiguration.chatTags,
                chatConfiguration.chatReferenceTags,
                chatConfiguration.chatId);
            events = [];
            responses = {};
            rootNoteId = null;
            localStorage.removeItem('rootNoteId');

            // rootNoteId = localStorage.getItem('rootNoteId');
            // if (rootNoteId) {
            //     $chatAdapter.subscribeToEventAndResponses(rootNoteId);
            // }
        }
        prevChatConfiguration = chatConfiguration;
    }

    function getEventById(eventId) {
        let event = events.find(e => e.id === eventId);
        event = event || responseEvents.find(e => e.id === eventId);
        return event;
    }

    async function sendMessage() {
        const input = document.getElementById('message-input');
        const message = input.value;
        input.value = '';
        let extraParams = { tags: [], tagPubKeys: [] };

        // if this is the rootLevel we want to tag the owner of the site's pubkey
        if (!rootNoteId && websiteOwnerPubkey) { extraParams.tagPubKeys = [websiteOwnerPubkey] }

        // if we are responding to an event, we want to tag the event and the pubkey
        if ($selectedMessage) {
            extraParams.tags.push(['e', $selectedMessage, "wss://nos.lol", "root"]);
            extraParams.tagPubKeys.push(getEventById($selectedMessage).pubkey);
        }

        // if (rootNoteId) {
        //     // mark it as a response to the most recent event
        //     const mostRecentEvent = events[events.length - 1];
        //     // go through all the tags and add them to the new message
        //     if (mostRecentEvent) {
        //         mostRecentEvent.tags.forEach(tag => {
        //             if (tag[0] === 'e') {
        //                 extraParams.tags.push(tag);
        //             }
        //         })
        //         extraParams.tags.push(['e', mostRecentEvent.id]);
        //         extraParams.tags.push(['p', mostRecentEvent.pubkey]);
        //     }
        // }

        const noteId = await $chatAdapter.send(message, extraParams);

        if (!rootNoteId) {
            rootNoteId = noteId;
            localStorage.setItem('rootNoteId', rootNoteId);
        }
    }

    async function inputKeyDown(event) {
        if (event.key === 'Enter') {
            sendMessage();
            event.preventDefault();
        }
    }

    function messageReceived(message) {
        const messageLastEventTag = message.tags.filter(tag => tag[0] === 'e').pop();
        let isThread;

        if (chatConfiguration.chatType === 'GLOBAL') {
            isThread = message.tags.filter(tag => tag[0] === 'e').length >= 1;
        } else if (chatConfiguration.chatType === 'GROUP') {
            isThread = message.tags.filter(tag => tag[0] === 'e' && tag[1] !== chatConfiguration.chatId).length >= 1;
        } else {
            const pubkeysTagged = message.tags.filter(tag => tag[0] === 'p').map(tag => tag[1]);
            isThread = new Set(pubkeysTagged).size >= 2;
        }

        if (!responses[message.id]) { responses[message.id] = [] };

        if (isThread) {
            // get the last "e" tag, which is tagging the immediate parent
            const lastETag = message.tags.filter(tag => tag[0] === 'e').pop();
            if (lastETag && lastETag[1]) {
                // if there is one, add it to the response
                if (!responses[lastETag[1]]) {
                    responses[lastETag[1]] = [];
                }
                responses[lastETag[1]].push(message);
            }

            responseEvents.push(message);
            responseEvents = responseEvents;
        } else {
            // insert message so that it's chronologically ordered by created_at
            let index = 0;
            while (index < events.length && events[index].created_at < message.created_at) {
                index++;
            }
            events.splice(index, 0, message);
            events = events;
        }

        responses = responses;

        scrollDown()
    }

    function scrollDown() {
        animateScroll.scrollToBottom({
            container: document.getElementById('messages-container'),
            offset: 999999, // hack, oh well, browsers suck
            duration: 50
        })
    }

    function zapReceived(zap) {
        const event = events.find(event => event.id === zap.zappedEvent);
        if (!event) { return; }

        if (!$zapsPerMessage[event.id]) $zapsPerMessage[event.id] = [];
        $zapsPerMessage[event.id].push(zap);
    }

    function reactionReceived(reaction) {
        const event = events.find(event => event.id === reaction.id);
        if (!event) { return; }

        event.reactions = event.reactions || [];
        event.reactions.push(reaction);
        events = events;
    }

    let rootNoteId;
    let channelMetadata = {};

    onMount(() => {
        $chatAdapter.on('message', messageReceived);

        $chatAdapter.on('connectivity', (e) => {
            connectivityStatus = e;
        })

        $chatAdapter.on('reaction', reactionReceived);
        $chatAdapter.on('zap', zapReceived);
        $chatAdapter.on('deleted', (deletedEvents) => {
            deletedEvents.forEach(deletedEventId => {
                const index = events.findIndex(event => event.id === deletedEventId);
                if (index !== -1) {
                    events[index].deleted = true;
                    events = events;
                }
            })
        });

        $chatAdapter.on('profile', ({pubkey, profile}) => {
            let profiles = $chatData.profiles;
            profiles[pubkey] = profile;

            chatData.set({ profiles, ...$chatData })
        })

        $chatAdapter.on('channelMetadata', (event) => {
            channelMetadata = JSON.parse(event.content);
        })
    });

    let connectivityStatus = {};
    let connectedRelays = 0;
    let totalRelays = 0;

    $: {
        connectedRelays = Object.values(connectivityStatus).filter(status => status === 'connected').length;
        totalRelays = Object.values(connectivityStatus).length;

        if ($chatAdapter?.pubkey && !profiles[$chatAdapter.pubkey]) {
            $chatAdapter.reqProfile($chatAdapter.pubkey)
        }
    }

    let connectedChatId;

    $: if (connectedChatId !== $chatAdapter?.chatId) {
        connectedChatId = $chatAdapter?.chatId;
        channelMetadata = {};
    }

    $: profiles = $chatData.profiles;

    function selectParent() {
        if (chatConfiguration.chatType === 'GROUP') {
            $selectedMessage = null;
        } else {
            // get the last tagged event in the tags array of the current $selectedMessage
            const lastETag = getEventById($selectedMessage).tags.filter(tag => tag[0] === 'e').pop();
            const lastETagId = lastETag && lastETag[1];

            $selectedMessage = lastETagId;
        }

        scrollDown()
    }

    let ownName;
    $: ownName = $chatAdapter?.pubkey ? pubkeyName($chatAdapter.pubkey) : "";

    function pubkeyName(pubkey) {
        let name;

        if (profiles[$chatAdapter.pubkey]) {
            let self = profiles[$chatAdapter.pubkey];

            // https://xkcd.com/927/
            name = self.display_name ||
                    self.displayName ||
                    self.name ||
                    self.nip05;

        }

        if (!name) { name = `Anonymous [${pubkey.slice(0, 6)}]`; }

        return name;
    }

</script>

<div class="
    bg-purple-700 text-white
    -mx-4 -mt-5 mb-3
    px-4 py-3
    overflow-clip
    flex flex-row justify-between items-center
">

    <div class="text-lg font-semibold">
        {#if $chatAdapter?.pubkey}
            {ownName}
        {/if}
    </div>

    <span class="text-xs flex flex-col items-end mt-2 text-gray-200 gap-1">
        <div class="flex flex-row gap-1 overflow-clip">
            {#each Array(totalRelays) as _, i}
                <span class="
                    inline-block
                    rounded-full
                    {connectedRelays > i ? 'bg-green-500' : 'bg-gray-300'}
                    w-2 h-2
                "></span>
            {/each}
        </div>

        {connectedRelays}/{totalRelays} relays
    </span>
</div>

{#if channelMetadata.name}
    <div class="flex flex-row gap-2 mb-3 bg-zinc-300 text-zinc-800 px-4 py-2 -mx-4 -mt-3">
        {#if channelMetadata.picture}
            <img src={channelMetadata.picture} class="w-12 h-12 rounded-full" />
        {/if}

        <div class="flex flex-col">
            <div class="font-extrabold text-xl">{channelMetadata.name}</div>
            {#if channelMetadata.about}
                <div class="text-sm truncate font-regular">{channelMetadata.about}</div>
            {/if}
        </div>
    </div>
{/if}

{#if $selectedMessage}
    {#if !getEventById($selectedMessage)}
        <h1>Couldn't find event with ID {$selectedMessage}</h1>
    {:else}
    <div class="flex flex-row mb-3">
        <a href='#' on:click|preventDefault={selectParent}>
            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
                <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12h-15m0 0l6.75 6.75M4.5 12l6.75-6.75" />
            </svg>
        </a>

        <div class="flex flex-col ml-2">
            <span class="text-lg text-black overflow-hidden whitespace-nowrap text-ellipsis">
                {getEventById($selectedMessage).content}
            </span>
        </div>
    </div>
    {/if}
{/if}

<div id="messages-container" class="overflow-auto -mx-4 px-4" style="height: 50vh; min-height: 300px;">
    <div id="messages-container-inner" class="flex flex-col gap-4">
        {#if $selectedMessage}
            <NostrNote event={getEventById($selectedMessage)} {responses} {websiteOwnerPubkey} />
        {:else}
            {#each events as event}
                <NostrNote {event} {responses} {websiteOwnerPubkey} />
                {#if event.deleted}
                    👆 deleted
                {/if}
            {:else}
                <p>no comments</p>
            {/each}
        {/if}
    </div>
</div>


<div class="flex flex-col">
    <!-- <div class="
        border-y border-y-slate-200
        -mx-4 my-2 bg-slate-100 text-black text-sm
        px-4 py-2
    ">
        {#if chatConfiguration.chatType === 'DM'}
            <b>Encrypted chat:</b>
            only your chat partner can see these messages.
        {:else if chatConfiguration.chatType === 'GROUP'}
            <b>Public chat:</b>
            anyone can see these messages.
        {:else}
            <b>Public notes:</b>
            your followers see your messages on their timeline
        {/if}
    </div> -->

    <div class="flex flex-row gap-2 -mx-1">
        <textarea
            type="text"
            id="message-input"
            class="
                -mb-2
                p-2
                w-full
                resize-none
                rounded-xl
                text-gray-600
                border
            " placeholder="leave a comment"
            rows=1
            on:keydown={inputKeyDown}
        ></textarea>
        <button type="button" class="inline-flex items-center rounded-full border border-transparent bg-purple-700 p-3 text-white shadow-sm hover:bg-purple-600 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2" on:click|preventDefault={sendMessage}>
            <!-- Heroicon name: outline/plus -->
            <svg aria-hidden="true" class="w-6 h-6 rotate-90" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10.894 2.553a1 1 0 00-1.788 0l-7 14a1 1 0 001.169 1.409l5-1.429A1 1 0 009 15.571V11a1 1 0 112 0v4.571a1 1 0 00.725.962l5 1.428a1 1 0 001.17-1.408l-7-14z"></path></svg>
        </button>
    </div>
</div>

<style>
	@tailwind base;
	@tailwind components;
	@tailwind utilities;
</style>