import BuddyChatHistoryManager from '../managers/buddy-chat-history-manager.js';
import LobbyController from '../controllers/lobby-controller.js';

export default class BuddyList extends HTMLElement
{
    static CHAT_CLICK_EVT = 'chat-click';
    static BLOCK_CLICK_EVT = 'block-click';
    static REMOVE_CLICK_EVT = 'remove-click';
    static ADD_CLICK_EVT = 'add-click';

    constructor()
    {
        super();

        this._shadowRoot = this.attachShadow({ mode: 'closed' });
    
        this._shadowRoot.innerHTML = `
            <link href="./assets/css/bootstrap.min.css" rel="stylesheet" />
            <link href="./assets/icons/css/fontawesome.min.css" rel="stylesheet" />
            <link href="./assets/icons/css/solid.min.css" rel="stylesheet" />

            <ul class="list-group list-group-flush">
                <template>
                    <li class="list-group-item px-0" data-buddy-name="">
                        <div class="hstack gap-2">
                            <div class="buddy-state">
                                <i class="fa-solid fa-user fa-lg fa-fw buddy-icon-unblocked"></i>
                                <i class="fa-solid fa-user-slash fa-lg fa-fw buddy-icon-blocked"></i>
                            </div>
                            <div class="flex-grow-1 d-flex flex-column">
                                <span><strong class="buddy-name">Buddy name</strong> <small class="text-secondary buddy-age">age</small></span>
                                <small class="buddy-mood">Buddy mood</small>
                            </div>
                            <i class="fa-solid fa-asterisk fa-2xs text-secondary buddy-icon-temp"></i>
                            <button type="button" class="btn btn-primary btn-sm position-relative chat-button">
                                <i class="fa-solid fa-comment"></i>
                                <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger buddy-badge" hidden>
                                    <span class="buddy-badge-cnt">0</span>
                                    <span class="visually-hidden">unread messages</span>
                                </span>
                            </button>
                            <button type="button" class="btn btn-outline-secondary btn-sm block-button"><i class="fa-solid fa-lock icon-block"></i><i class="fa-solid fa-unlock icon-unblock"></i></button>
                            <button type="button" class="btn btn-outline-secondary btn-sm remove-button"><i class="fa-solid fa-circle-xmark"></i></button>
                            <button type="button" class="btn btn-outline-secondary btn-sm add-button"><i class="fa-solid fa-circle-plus"></i></button>
                        </div>
                    </li>
                </template>
            </ul>
        `;

        this.list = this._shadowRoot.querySelector('ul');

        // Bind event listeners
        this.onBoundChatButtonClick = this.onChatButtonClick.bind(this);
        this.onBoundBlockButtonClick = this.onBlockButtonClick.bind(this);
        this.onBoundRemoveButtonClick = this.onRemoveButtonClick.bind(this);
        this.onBoundAddButtonClick = this.onAddButtonClick.bind(this);
    }

    connectedCallback()
    {
        // Nothing to do
    }

    reset()
    {
        for (let item of this.list.querySelectorAll('li[data-buddy-name'))
            this.removeListItem(item.dataset.buddyName);
    }

    addListItem(buddy, toTop = false)
    {
        // Check if buddy list item already exist
        // This could happen if a temporary buddy is added permanently
        if (this.getListItem(buddy.name) != null)
        {
            this.setItemState(buddy);
        }
        else
        {
            // Create buddy list item from template
            const template = this.list.querySelector('template');
            let node = template.content.cloneNode(true);
            node.firstElementChild.dataset.buddyName = buddy.name;

            // Add buddy list item to container
            this.list.append(node);

            if (toTop)
                this.moveListItemToTop(buddy.name)

            // Update buddy list item
            this.setItemState(buddy);

            // Set unread messages counter
            // (buddy could have sent messages while user was in the game scene)
            this.setItemChatMsgCounter(buddy.name, BuddyChatHistoryManager.getUnreadMessagesCount(buddy.name));

            // Add listeners to buttons
            const item = this.getListItem(buddy.name);
            item.querySelector('.chat-button').addEventListener('click', this.onBoundChatButtonClick);
            item.querySelector('.block-button').addEventListener('click', this.onBoundBlockButtonClick);
            item.querySelector('.remove-button').addEventListener('click', this.onBoundRemoveButtonClick);
            item.querySelector('.add-button').addEventListener('click', this.onBoundAddButtonClick);
        }
    }

    moveListItemToTop(buddyName)
    {
        const item = this.getListItem(buddyName);

        this.list.prepend(item);

        // Always keep template at the top of the list
        this.list.prepend(this.list.querySelector('template'));
    }

    updateListItem(buddy)
    {
        // Get reference to buddy list item corresponding to Buddy
        const item = this.getListItem(buddy.name);

        if (item != null)
        {
            // Check if the update was caused by a block/unblock request
            if (buddy.isBlocked != item.dataset.buddyBlocked)
            {
                // Move buddy to the bottom of the list if blocked, to top otherwise
                if (buddy.isBlocked)
                    this.list.append(item);
                else
                    this.moveListItemToTop(buddy.name);
            }

            // Update buddy list item
            this.setItemState(buddy);
        }
    }

    getListItem(buddyName)
    {
        return this.list.querySelector(`li[data-buddy-name="${buddyName}"`);
    }

    setItemState(buddy)
    {
        const item = this.getListItem(buddy.name);

        // Nickname
        item.querySelector('.buddy-name').innerText = buddy.displayName;

        // Age
        const now = new Date();
        const yearVar = buddy.getVariable(LobbyController.BUDDYVAR_YEAR);

        item.querySelector('.buddy-age').innerText = (yearVar != null && !yearVar.isNull) ? `(${now.getFullYear() - yearVar.value} yo)` : '';

        // Mood
        const moodElem = item.querySelector('.buddy-mood');
        const moodVar = buddy.getVariable(LobbyController.BUDDYVAR_MOOD);
        
        if (moodVar != null && !moodVar.isNull && moodVar.value != '')
        {
            moodElem.innerText = moodVar.value;
            moodElem.hidden = false;
        }
        else
        {
            moodElem.innerText = '';
            moodElem.hidden = true;
        }

        // Temporary
        item.querySelector('.buddy-icon-temp').hidden = !buddy.isTemp;

        // Save blocked state
        // (see updateListItem method)
        item.dataset.buddyBlocked = buddy.isBlocked;

        // If buddy is not blocked and is temporary, show add button and hide remove button
        const showAddButton = !buddy.isBlocked && buddy.isTemp;
        item.querySelector('.add-button').hidden = !showAddButton;
        item.querySelector('.remove-button').hidden = showAddButton;

        // Status icon and buttons
        item.querySelector('.buddy-state').classList = ['buddy-state'];

        if (buddy.isBlocked)
        {
            // State
            item.querySelector('.buddy-state').classList.add('opacity-25');
            item.querySelector('.buddy-icon-blocked').hidden = false;
            item.querySelector('.buddy-icon-unblocked').hidden = true;

            // Block/unblock button
            item.querySelector('.icon-block').hidden = true;
            item.querySelector('.icon-unblock').hidden = false;

            // Chat button
            this.enableItemChatButton(buddy.name, false);
            this.setItemChatMsgCounter(buddy.name, 0);
        }
        else
        {
            // State
            item.querySelector('.buddy-icon-blocked').hidden = true;
            item.querySelector('.buddy-icon-unblocked').hidden = false;

            // Block/unblock button
            item.querySelector('.icon-block').hidden = false;
            item.querySelector('.icon-unblock').hidden = true;

            if (!buddy.isOnline)
            {
                // State
                item.querySelector('.buddy-state').classList.add('opacity-25');

                // Chat button
                this.enableItemChatButton(buddy.name, false);
                this.setItemChatMsgCounter(buddy.name, 0);
            }
            else
            {
                // State
                const state = buddy.state;

                if (state == 'Available')
                    item.querySelector('.buddy-state').classList.add('text-success');
                else if (state == 'Away')
                    item.querySelector('.buddy-state').classList.add('text-warning');
                else if (state == 'Occupied')
                    item.querySelector('.buddy-state').classList.add('text-danger');

                // Chat button
                this.enableItemChatButton(buddy.name, true);
            }
        }
    }

    removeListItem(buddyName)
    {
        const item = this.getListItem(buddyName);

        // Remove listeners from buttons
        item.querySelector('.chat-button').removeEventListener('click', this.onBoundChatButtonClick);
        item.querySelector('.block-button').removeEventListener('click', this.onBoundBlockButtonClick);
        item.querySelector('.add-button').removeEventListener('click', this.onBoundAddButtonClick);
        item.querySelector('.remove-button').removeEventListener('click', this.onBoundRemoveButtonClick);

        // Remove buddy list item
        this.list.removeChild(item);
    }

    setItemChatMsgCounter(buddyName, cnt)
    {
        const item = this.getListItem(buddyName);
        
        item.querySelector('.buddy-badge-cnt').innerText = cnt;
        item.querySelector('.buddy-badge').hidden = (cnt <= 0);
    }
    
    enableItemChatButton(buddyName, enable)
    {
        const item = this.getListItem(buddyName);
        item.querySelector('.chat-button').disabled = !enable;
    }

    getItemData(element)
    {
        return element.closest('li').dataset.buddyName;
    }

    onChatButtonClick(e)
    {
        this.dispatchEvent(
            new CustomEvent(BuddyList.CHAT_CLICK_EVT, {
                detail: {
                    buddyName: this.getItemData(e.currentTarget)
                }
            })
        );
    }

    onBlockButtonClick(e)
    {
        this.dispatchEvent(
            new CustomEvent(BuddyList.BLOCK_CLICK_EVT, {
                detail: {
                    buddyName: this.getItemData(e.currentTarget)
                }
            })
        );
    }

    onRemoveButtonClick(e)
    {
        this.dispatchEvent(
            new CustomEvent(BuddyList.REMOVE_CLICK_EVT, {
                detail: {
                    buddyName: this.getItemData(e.currentTarget)
                }
            })
        );
    }

    onAddButtonClick(e)
    {
        this.dispatchEvent(
            new CustomEvent(BuddyList.ADD_CLICK_EVT, {
                detail: {
                    buddyName: this.getItemData(e.currentTarget)
                }
            })
        );
    }
}

customElements.define('buddy-list', BuddyList);