import * as bootstrap from 'bootstrap';
import LobbyController from '../controllers/lobby-controller.js';

export default class GameLauncher extends HTMLElement
{
    static SHOW_EVT = 'show';
    static START_CLICK_EVT = 'start-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" />

            <button id="newGameButton" type="button" class="btn btn-primary"><i class="fa-solid fa-plus"></i></button>
            <div class="modal" id="startGameModal" tabindex="-1" aria-labelledby="startGameModalLabel" aria-hidden="true">
                <div class="modal-dialog modal-dialog-centered modal-lg">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h1 class="modal-title fs-5" id="startGameModalLabel">New Game</h1>
                            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                        </div>
                        <div class="modal-body">
                            <div class="row g-5">
                                <div class="col-lg-6">
                                    <div class="pb-3">
                                        <div class="form-check">
                                            <input class="form-check-input" type="checkbox" id="publicGameCheck">
                                            <label class="form-check-label" for="publicGameCheck">Game is public</label>
                                        </div>
                                    </div>
                                    <div class="pb-3">
                                        <h6>Matching Criteria</h6>
                                        <div class="vstack gap-1">
                                            <span>Experience = <strong id="expLabel"></strong></span>
                                            <span>Ranking ≥ <strong id="rankLabel"></strong></span>
                                        </div>
                                    </div>
                                    <small class="text-secondary">If game is private, automatic invitations will be sent based on the matching criteria to fill the available player slot. Force invitation to be sent to a buddy (overriding the matching criteria) by selecting their name on the right.</small>
                                </div>
                                <div class="col-lg-6">
                                    <div class="pb-3">
                                        <h6>Invitation Message</h6>
                                        <input type="text" class="form-control" id="invitationMsgInput" value="Do you want to join my game?">
                                    </div>
                                    <div class="pb-3">
                                        <h6>Invite Buddy</h6>
                                        <div id="offlineAlert" class="alert alert-warning" role="alert" hidden>You are offline; you can't invite buddies.</div>
                                        <fieldset id="buddyRadiosFieldset">
                                            <template>
                                                <div data-buddy-name="" class="form-check">
                                                    <input class="form-check-input" type="radio" name="invitee" value="" id="">
                                                    <label class="form-check-label" for=""></label>
                                                </div>
                                            </template>
                                        </fieldset>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="modal-footer justify-content-center">
                            <button id="startButton" type="button" class="btn btn-primary w-50"><i class="fa-solid fa-rocket"></i> Start</button>
                        </div>
                    </div>
                </div>
            </div>
        `;

        this.newGameButton = this._shadowRoot.querySelector('#newGameButton');
        this.publicGameCheck = this._shadowRoot.querySelector('#publicGameCheck');
        this.expLabel = this._shadowRoot.querySelector('#expLabel');
        this.rankLabel = this._shadowRoot.querySelector('#rankLabel');
        this.invitationMsgInput = this._shadowRoot.querySelector('#invitationMsgInput');
        this.buddyRadiosFieldset = this._shadowRoot.querySelector('#buddyRadiosFieldset');
        this.offlineAlert = this._shadowRoot.querySelector('#offlineAlert');
        this.startButton = this._shadowRoot.querySelector('#startButton');

        // Create start game modal
        this.startGameModal = new bootstrap.Modal(this._shadowRoot.querySelector('#startGameModal'), {
            backdrop: true,
            focus: true,
            keyboard: true
        });

        // Bind event listeners
        this.boundOnNewGameButtonClick = this.onNewGameButtonClick.bind(this);
        this.boundOnPublicGameCheckChange = this.onPublicGameCheckChange.bind(this);
        this.boundOnStartButtonClick = this.onStartButtonClick.bind(this);
    }

    connectedCallback()
    {
        // Add listeners
        this.newGameButton.addEventListener('click', this.boundOnNewGameButtonClick);
        this.publicGameCheck.addEventListener('change', this.boundOnPublicGameCheckChange);
        this.startButton.addEventListener('click', this.boundOnStartButtonClick);
    }

    get invitationMessage()
    {
        return this.invitationMsgInput.value;
    }

    init(isUserOnline, userExp, userRank)
    {
        this.publicGameCheck.checked = true;
        this.enableInvitations(false);

        const buddyRadios = this.buddyRadiosFieldset.querySelectorAll('input[type="radio"]');
        buddyRadios.forEach(buddyRadio => {
            buddyRadio.checked = false;
        });

        this.expLabel.innerText = userExp;
        this.rankLabel.innerText = userRank;

        // Show/hide buddy list
        this.buddyRadiosFieldset.hidden = !isUserOnline;
        this.offlineAlert.hidden = isUserOnline;
    }

    getInviteListItem(buddyName)
    {
        return this.buddyRadiosFieldset.querySelector(`div[data-buddy-name="${buddyName}"`);
    }

    updateInviteList(buddy, doRemove = false)
    {
        // Get invite list item corresponding to buddy
        let inviteListItem = this.getInviteListItem(buddy.name);

        if (inviteListItem != null)
        {
            if (doRemove)
            {
                // Remove invite list item
                inviteListItem.remove();
            }
            else
            {
                // Update existing item
                this.setInviteListItemState(inviteListItem, buddy);
            }
        }
        else
        {
            // Create invite list item from template
            const template = this.buddyRadiosFieldset.getElementsByTagName('template')[0];
            const node = template.content.cloneNode(true);
            node.firstElementChild.dataset.buddyName = buddy.name;
            
            const radio = node.firstElementChild.getElementsByTagName('input')[0];
            radio.value = buddy.name;
            radio.id = 'radio_' + buddy.name;
            radio.checked = false;

            const label = node.firstElementChild.getElementsByTagName('label')[0];
            label.htmlFor = radio.id;

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

            // Get reference to newly created element
            inviteListItem = this.getInviteListItem(buddy.name);

            // Init invite list toggle
            this.setInviteListItemState(inviteListItem, buddy);
        }
    }

    setInviteListItemState(inviteListItem, buddy)
    {
        const radio = inviteListItem.getElementsByTagName('input')[0];
        const label = inviteListItem.getElementsByTagName('label')[0];

        // Nickname
        label.innerText = buddy.displayName;

        // Status
        radio.disabled = buddy.isBlocked || !buddy.isOnline || buddy.state == 'Away';

        if (radio.disabled)
            radio.checked = false;
    }

    enableInvitations(enable)
    {
        this.invitationMsgInput.disabled = !enable;
        this.buddyRadiosFieldset.disabled = !enable;
    }

    // -------------------------------------------------------------------

    onNewGameButtonClick(e)
    {
        this.startGameModal.show();

        // Fire event
        this.dispatchEvent(
            new CustomEvent(GameLauncher.SHOW_EVT)
        );
    }

    onPublicGameCheckChange(e)
    {
        const isChecked = e.currentTarget.checked;

        this.enableInvitations(!isChecked);
    }

    onStartButtonClick(e)
    {
        // Get invited buddy
        let invitedBuddyName = null;

        const invitedItemRadio = this.buddyRadiosFieldset.querySelector('input[type="radio"]:checked');

        if (invitedItemRadio != null)
            invitedBuddyName = invitedItemRadio.value;

        // Dispatch event
        this.dispatchEvent(
            new CustomEvent(GameLauncher.START_CLICK_EVT, {
                detail: {
                    isPublic: this.publicGameCheck.checked,
                    buddyName: invitedBuddyName
                }
            })
        );

        // Hide modal
        this.startGameModal.hide();
    }
}

customElements.define('game-launcher', GameLauncher);