import BaseController from './base-controller.js';
import ChatPanel from '../components/chat-panel.js';
import { SFSEvent, EventParam } from 'sfs3-api';
import { LeaveRoomRequest, PublicMessageRequest } from 'sfs3-api';
import * as bootstrap from 'bootstrap';

export default class GameController extends BaseController
{
    constructor(app, view, name)
    {
        super(app, view, name);

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

        this.leaveGameButton = view.querySelector('#leaveGameButton');
        this.leaveGameModalButton = view.querySelector('#leaveGameModalButton');
        this.chatTab = view.querySelector('#chatTab');
        this.chatPanel = view.querySelector('#chatPanel');
    }

    //----------------------------------------------------------
    // Overridden methods
    //----------------------------------------------------------

    initialize()
    {
        super.initialize();

        // Add leave game buttons click listener
        this.boundOnLeaveGameButtonClick = this.onLeaveGameButtonClick.bind(this);
        this.leaveGameButton.addEventListener('click', this.boundOnLeaveGameButtonClick);
        this.leaveGameModalButton.addEventListener('click', this.boundOnLeaveGameButtonClick);

        // Add tabs show listener
        this.boundOnChatTabShow = this.onChatTabShow.bind(this);
        this.chatTab.addEventListener('shown.bs.tab', this.boundOnChatTabShow);
                
        // Create timeout modal
        this.timeoutModal = new bootstrap.Modal(this.view.querySelector('#timeoutModal'), {
            backdrop: true,
            focus: true,
            keyboard: true
        });

        // Add custom event "message submit" listener to chat panel
        this.boundOnChatPanelMsgSubmit = this.onChatPanelMsgSubmit.bind(this);
        this.chatPanel.addEventListener(ChatPanel.MESSAGE_SUBMIT_EVT, this.boundOnChatPanelMsgSubmit);

        // Print system message
        this.chatPanel.printSystemMessage('Game joined as ' + (this.sfs.mySelf.isPlayer ? 'player' : 'spectator'));

        // Add SFS event listeners
        this.sfs.addEventListener(SFSEvent.PUBLIC_MESSAGE, this.onPublicMessage, this);
        this.sfs.addEventListener(SFSEvent.USER_ENTER_ROOM, this.onUserEnterRoom, this);
        this.sfs.addEventListener(SFSEvent.USER_EXIT_ROOM, this.onUserExitRoom, this);

        // If user is the first player in the Room, set a timeout
        // Having a timeout is usefult to suggest the user to leave the game if not yet started within some time
        // For example this could mean that the invited buddy refused the invitation, or the server couldn't locate other players to invite
        if (this.sfs.mySelf.isPlayer && this.sfs.lastJoinedRoom.playerList.length == 1)
            this.waitTimeout = setTimeout(this.onPlayerWaitTimeout.bind(this), 20000);

        // Show view
        this.showView();
    }

    destroy()
    {
        super.destroy(); // This also calls removeSmartFoxListeners method!

        // Dispose timeout modal
        clearTimeout(this.waitTimeout);
        this.timeoutModal.dispose();

        // Remove leave game buttons click listener
        this.leaveGameButton.removeEventListener('click', this.boundOnLeaveGameButtonClick);
        this.leaveGameModalButton.removeEventListener('click', this.boundOnLeaveGameButtonClick);

        // Show initial tab
        const triggerFirstTabEl = this.view.querySelector('#gameViewTabs li:first-child button');
        bootstrap.Tab.getInstance(triggerFirstTabEl).show();

        // Reset unread message counter
        this.updateUnreadMsgCounter(true);

        // Remove custom event "message submit" listener from chat panel
        this.chatPanel.removeEventListener(ChatPanel.MESSAGE_SUBMIT_EVT, this.boundOnChatPanelMsgSubmit);

        // Reset chat panel
        this.chatPanel.reset();
    }

    removeSmartFoxListeners()
    {
        if (this.sfs != null)
        {
            this.sfs.removeEventListener(SFSEvent.PUBLIC_MESSAGE, this.onPublicMessage);
            this.sfs.removeEventListener(SFSEvent.USER_ENTER_ROOM, this.onUserEnterRoom);
            this.sfs.removeEventListener(SFSEvent.USER_EXIT_ROOM, this.onUserExitRoom);
        }
    }

    //----------------------------------------------------------
    // Other methods
    //----------------------------------------------------------

    updateUnreadMsgCounter(forceReset = false)
    {
        const counterNode = this.view.querySelector('#unreadMsgCnt');

        let value = 0;

        // If chat is visible, always set number of unread messages to zero, otherwise increase current value
        const isChatVisible = this.view.querySelector('#chatPane').checkVisibility();
        if (!isChatVisible && !forceReset)
        {
            // Get current value and increase it by one
            value = Number(counterNode.innerText) + 1;
        }

        // Set value
        counterNode.innerText = value;

        // If value is 0, hide badge
        this.view.querySelector('#unreadMsgContainer').hidden = (value == 0);
    }

    //----------------------------------------------------------
    // UI event listeners
    //----------------------------------------------------------

    onLeaveGameButtonClick(e)
	{
		// Leave current game room
        this.sfs.send(new LeaveRoomRequest());

        // Return to lobby view
        this.app.goToView('lobby');
	}

    onChatTabShow(e)
    {
        this.updateUnreadMsgCounter();
    }

    onPlayerWaitTimeout(e)
    {
        this.timeoutModal.show();
    }

    onChatPanelMsgSubmit(e)
    {
        const msg = e.detail.message;

        // Send public message to Room
        this.sfs.send(new PublicMessageRequest(msg));
    }

    //----------------------------------------------------------
    // SmartFoxServer event listeners
    //----------------------------------------------------------
    
    onPublicMessage(evtParams)
    {
        const sender = evtParams[EventParam.Sender];
        const message = evtParams[EventParam.Message];

        // Display chat message
        this.chatPanel.printChatMessage(message, sender.name, sender == this.sfs.mySelf);

        // Update unread messages counter
        if (sender != this.sfs.mySelf)
            this.updateUnreadMsgCounter();
    }

    onUserEnterRoom(evtParams)
    {
        const user = evtParams[EventParam.User];
        const room = evtParams[EventParam.Room];

        // Display system message
        this.chatPanel.printSystemMessage(`User <strong>${user.name}</strong> joined this game as ${user.isPlayerInRoom(room) ? 'player' : 'spectator'}`);

        if (user.isPlayerInRoom(room))
        {
            // Stop timeout
            clearTimeout(this.waitTimeout);

            // Hide leave modal
            this.timeoutModal.hide();
        }
    }

    onUserExitRoom(evtParams)
    {
        const user = evtParams[EventParam.User];

        // Display system message
        if (user != this.sfs.mySelf)
            this.chatPanel.printSystemMessage(`User <strong>${user.name}</strong> left the game`);
    }
}