import * as bootstrap from 'bootstrap';
import BaseController from './base-controller.js';
import ProfileConfigurator from '../components/profile-configurator.js';
import BuddyChatHistoryManager from '../managers/buddy-chat-history-manager.js';
import GameList from '../components/game-list.js';
import BuddyList from '../components/buddy-list.js';
import ChatPanel from '../components/chat-panel.js';
import { SFSObject, SFSEvent, SFSBuddyEvent, EventParam, SFSBuddyVariable, VariableType, ReservedBuddyVariables } from 'sfs3-api';
import { RoomSettings, CreateRoomRequest, JoinRoomRequest } from 'sfs3-api';
import { InitBuddyListRequest, AddBuddyRequest, RemoveBuddyRequest, BlockBuddyRequest, GoOnlineRequest, SetBuddyVariablesRequest, BuddyMessageRequest } from 'sfs3-api';

export default class LobbyController extends BaseController
{
    static GAME_ROOMS_GROUP_NAME = 'games';
    static BUDDYVAR_YEAR = SFSBuddyVariable.OFFLINE_PREFIX + 'year';
    static BUDDYVAR_MOOD = 'mood';

    constructor(app, view, name)
    {
        super(app, view, name);

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

        this.logoutButton = view.querySelector('#logoutButton');
        this.profileConfigurator = view.querySelector('#profileConfigurator');
        this.gameList = view.querySelector('#gameList');
        this.newGameButton = view.querySelector('#newGameButton');
        this.buddyList = view.querySelector('#buddyList');
        this.addBuddyForm = view.querySelector('#addBuddyForm');
        this.buddyNameInput = view.querySelector('#buddyNameInput');
        this.buddyListTab = view.querySelector('#buddyListTab')
        this.buddyListPane = view.querySelector('#buddyListPane')
        this.buddyChatTab = view.querySelector('#buddyChatTab')
        this.buddyChatPane = view.querySelector('#buddyChatPane');
        this.buddyChatPanel = view.querySelector('#buddyChatPanel');
    }

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

    initialize()
    {
        super.initialize();

        // Add logout button click listener
        this.boundOnLogoutButtonClick = this.onLogoutButtonClick.bind(this);
        this.logoutButton.addEventListener('click', this.boundOnLogoutButtonClick);

        // Add "new game" button click listener
        this.boundOnNewGameButtonClick = this.onNewGameButtonClick.bind(this);
        this.newGameButton.addEventListener('click', this.boundOnNewGameButtonClick);

        // Add listener to join button click event fired by GameList class
        this.boundOnJoinGameClickEvent = this.onJoinGameClickEvent.bind(this);
        this.gameList.addEventListener(GameList.JOIN_CLICK_EVT, this.boundOnJoinGameClickEvent);

        // Add listeners to events fired by BuddyList class
        this.boundOnBuddyChatClickEvent = this.onBuddyChatClickEvent.bind(this);
        this.buddyList.addEventListener(BuddyList.CHAT_CLICK_EVT, this.boundOnBuddyChatClickEvent);

        this.boundOnBuddyBlockClickEvent = this.onBuddyBlockClickEvent.bind(this);
        this.buddyList.addEventListener(BuddyList.BLOCK_CLICK_EVT, this.boundOnBuddyBlockClickEvent);

        this.boundOnBuddyRemoveClickEvent = this.onBuddyRemoveClickEvent.bind(this);
        this.buddyList.addEventListener(BuddyList.REMOVE_CLICK_EVT, this.boundOnBuddyRemoveClickEvent);

        this.boundOnBuddyAddClickEvent = this.onBuddyAddClickEvent.bind(this);
        this.buddyList.addEventListener(BuddyList.ADD_CLICK_EVT, this.boundOnBuddyAddClickEvent);

        // Add listeners to events fired by ProfileConfigurator class
        this.boundOnOnlineToggleChangeEvent = this.onOnlineToggleChangeEvent.bind(this);
        this.profileConfigurator.addEventListener(ProfileConfigurator.ONLINE_CHANGE_EVT, this.boundOnOnlineToggleChangeEvent);

        this.boundOnBuddySettingChangeEvent = this.onBuddySettingChangeEvent.bind(this);
        this.profileConfigurator.addEventListener(ProfileConfigurator.BUDDY_SETTING_CHANGE_EVT, this.boundOnBuddySettingChangeEvent);

        // Add buddy form submit listener
        this.boundOnAddBuddyFormSubmit = this.onAddBuddyFormSubmit.bind(this);
        this.addBuddyForm.addEventListener('submit', this.boundOnAddBuddyFormSubmit);
        
        // Add listeners to events fired by ChatPanel class
        this.boundOnBuddyChatPanelCloseClick = this.onBuddyChatPanelCloseClick.bind(this);
        this.buddyChatPanel.addEventListener(ChatPanel.CLOSE_CLICK_EVT, this.boundOnBuddyChatPanelCloseClick);

        this.boundOnBuddyChatPanelMsgSubmit = this.onBuddyChatPanelMsgSubmit.bind(this);
        this.buddyChatPanel.addEventListener(ChatPanel.MESSAGE_SUBMIT_EVT, this.boundOnBuddyChatPanelMsgSubmit);

        // Add buddy chat tab show listener
        this.boundOnBuddyChatTabShow = this.onBuddyChatTabShow.bind(this);
        this.buddyChatTab.addEventListener('shown.bs.tab', this.boundOnBuddyChatTabShow);

        // Add SFS event listeners
        this.sfs.addEventListener(SFSEvent.ROOM_CREATION_ERROR, this.onRoomCreationError, this);
        this.sfs.addEventListener(SFSEvent.ROOM_ADD, this.onRoomAdded, this);
        this.sfs.addEventListener(SFSEvent.ROOM_REMOVE, this.onRoomRemoved, this);
        this.sfs.addEventListener(SFSEvent.USER_COUNT_CHANGE, this.onUserCountChanged, this);
        this.sfs.addEventListener(SFSEvent.ROOM_JOIN, this.onRoomJoin, this);
        this.sfs.addEventListener(SFSEvent.ROOM_JOIN_ERROR, this.onRoomJoinError, this);

		this.sfs.addEventListener(SFSBuddyEvent.BUDDY_LIST_INIT, this.onBuddyListInit, this);
		this.sfs.addEventListener(SFSBuddyEvent.BUDDY_ERROR, this.onBuddyError, this);
		this.sfs.addEventListener(SFSBuddyEvent.BUDDY_ONLINE_STATE_CHANGE, this.onBuddyOnlineStateChange, this);
		this.sfs.addEventListener(SFSBuddyEvent.BUDDY_VARIABLES_UPDATE, this.onBuddyVariablesUpdate, this);
		this.sfs.addEventListener(SFSBuddyEvent.BUDDY_BLOCK, this.onBuddyBlock, this);
		this.sfs.addEventListener(SFSBuddyEvent.BUDDY_REMOVE, this.onBuddyRemove, this);
		this.sfs.addEventListener(SFSBuddyEvent.BUDDY_ADD, this.onBuddyAdd, this);
		this.sfs.addEventListener(SFSBuddyEvent.BUDDY_MESSAGE, this.onBuddyMessage, this);
        
        // Populate list of available games
        const rooms = this.sfs.roomManager.getRoomList();
        this.gameList.populateList(rooms);

        // Display user name in profile modal
        this.profileConfigurator.displayUserName(this.sfs.mySelf.name);

        // Hide buddy list & chat panes
        this.showBuddyList(false);
        this.showBuddyChat(false);

        // Show unread chats counter
        this.updateUnreadBuddyChatsTabCounter();

        // Activate games tab
        bootstrap.Tab.getOrCreateInstance(this.view.querySelector(`#gamesTab`)).show();

        // Initialize Buddy List system
        // We have to check if it was already initialized if this scene is relaoded after leaving the Game scene
        if (!this.sfs.buddyManager.isInited)
            this.sfs.send(new InitBuddyListRequest());
        else
            this.initializeBuddyClient();

        // Show view
        this.showView();
    }

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

        // Remove logout button click listener
        this.logoutButton.removeEventListener('click', this.boundOnLogoutButtonClick);

        // Remove "new game" button click listener
        this.newGameButton.removeEventListener('click', this.boundOnNewGameButtonClick);

        // Remove buddy form submit listener
        this.addBuddyForm.addEventListener('submit', this.boundOnAddBuddyFormSubmit);

        // Remove listener to join button click event fired by GameList class
        this.gameList.removeEventListener(GameList.JOIN_CLICK_EVT, this.boundOnJoinGameClickEvent);

        // Remove listeners to events fired by BuddyList class
        this.buddyList.removeEventListener(BuddyList.CHAT_CLICK_EVT, this.boundOnBuddyChatClickEvent);
        this.buddyList.removeEventListener(BuddyList.BLOCK_CLICK_EVT, this.boundOnBuddyBlockClickEvent);
        this.buddyList.removeEventListener(BuddyList.REMOVE_CLICK_EVT, this.boundOnBuddyRemoveClickEvent);
        this.buddyList.removeEventListener(BuddyList.ADD_CLICK_EVT, this.boundOnBuddyAddClickEvent);

        // Remove listeners to events fired by ProfileConfigurator class
        this.profileConfigurator.removeEventListener(ProfileConfigurator.ONLINE_CHANGE_EVT, this.boundOnOnlineToggleChangeEvent);
        this.profileConfigurator.removeEventListener(ProfileConfigurator.BUDDY_SETTING_CHANGE_EVT, this.boundOnBuddySettingChangeEvent);

        // Remove listeners to events fired by ChatPanel class
        this.buddyChatPanel.removeEventListener(ChatPanel.CLOSE_CLICK_EVT, this.boundOnBuddyChatPanelCloseClick);
        this.buddyChatPanel.removeEventListener(ChatPanel.MESSAGE_SUBMIT_EVT, this.boundOnBuddyChatPanelMsgSubmit);

        // Remove buddy chat tab show listener
        this.buddyChatTab.removeEventListener('shown.bs.tab', this.boundOnBuddyChatTabShow);

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

        // Reset game list
        this.gameList.reset();

        // Reset buddy list
        this.buddyList.reset();
        
        // Reset chat panel
        this.buddyChatPanel.reset();
    }

    removeSmartFoxListeners()
    {
        if (this.sfs != null)
        {
            this.sfs.removeEventListener(SFSEvent.ROOM_CREATION_ERROR, this.onRoomCreationError);
            this.sfs.removeEventListener(SFSEvent.ROOM_ADD, this.onRoomAdded);
            this.sfs.removeEventListener(SFSEvent.ROOM_REMOVE, this.onRoomRemoved);
            this.sfs.removeEventListener(SFSEvent.USER_COUNT_CHANGE, this.onUserCountChanged);
            this.sfs.removeEventListener(SFSEvent.ROOM_JOIN, this.onRoomJoin);
            this.sfs.removeEventListener(SFSEvent.ROOM_JOIN_ERROR, this.onRoomJoinError);
            

			this.sfs.removeEventListener(SFSBuddyEvent.BUDDY_LIST_INIT, this.onBuddyListInit);
			this.sfs.removeEventListener(SFSBuddyEvent.BUDDY_ERROR, this.onBuddyError);
			this.sfs.removeEventListener(SFSBuddyEvent.BUDDY_ONLINE_STATE_UPDATE, this.onBuddyOnlineStateChange);
			this.sfs.removeEventListener(SFSBuddyEvent.BUDDY_VARIABLES_UPDATE, this.onBuddyVariablesUpdate);
			this.sfs.removeEventListener(SFSBuddyEvent.BUDDY_BLOCK, this.onBuddyBlock);
			this.sfs.removeEventListener(SFSBuddyEvent.BUDDY_REMOVE, this.onBuddyRemove);
			this.sfs.removeEventListener(SFSBuddyEvent.BUDDY_ADD, this.onBuddyAdd);
			this.sfs.removeEventListener(SFSBuddyEvent.BUDDY_MESSAGE, this.onBuddyMessage);
        }
    }

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

    showBuddyList(show)
    {
        // Show/hide buddy list tab and pane
        this.buddyListTab.hidden = !show;
        this.buddyListPane.hidden = !show;
    }

    showBuddyChat(show, buddy = null)
    {
        // Show/hide buddy list tab and pane
        this.buddyChatTab.hidden = !show;
        this.buddyChatPane.hidden = !show;

        if (show)
        {
            // Show buddy nick/name in tab
            const displayName = buddy.nickname ? buddy.nickname : buddy.name;
            this.view.querySelector(`#buddyChatTabLabel`).innerText = displayName;

            // Activate tab
            bootstrap.Tab.getOrCreateInstance(this.buddyChatTab).show();
        }
        else
        {
            // Remove buddy nick/name from tab
            this.view.querySelector(`#buddyChatTabLabel`).innerHTML = '';

            // Activate buddy list tab
            bootstrap.Tab.getOrCreateInstance(this.buddyListTab).show();
        }

        // Reset name in tag attribute
        this.buddyChatPanel.dataset.buddyName = (buddy != null ? buddy.name : '');
    }

    initializeBuddyClient()
    {
        // Display buddy list items
        // All blocked buddies are displayed at the bottom of the list
        for (let buddy of this.sfs.buddyManager.buddyList)
            this.buddyList.addListItem(buddy, !buddy.isBlocked);

        // Set current user details in Buddy List system
        this.profileConfigurator.initBuddyProfile(this.sfs.buddyManager);

        // Display user state in Buddy List system
        this.displayUserStateAsBuddy();

        // Show/hide buddy list
        this.showBuddyList(this.sfs.buddyManager.myOnlineState);
    }

    /**
     * Show current user state in Buddy List system in footer.
     */
    displayUserStateAsBuddy()
    {
        const state = this.sfs.buddyManager.myOnlineState ? this.sfs.buddyManager.myState : 'Offline';
        this.profileConfigurator.displayUserState(state);
    }

    updateBuddyListEntry(buddy)
    {
        this.buddyList.updateListItem(buddy);

        // Update buddy chat panel
        if (this.buddyChatPanel.dataset.buddyName == buddy.name)
            this.setBuddyChatPanelState(buddy);
    }

    initBuddyChatPanel(buddy, msgHistory)
    {
        // Set buddy name
        this.buddyChatPanel.dataset.buddyName = buddy.name;

        // Configure chat panel
        this.setBuddyChatPanelState(buddy);

        // Clear previous chat messages (panel is reused for different buddies)
        this.buddyChatPanel.reset();

        // Print chat history
        if (msgHistory != null)
            for (let messageObj of msgHistory)
                this.buddyChatPanel.printChatMessage(messageObj.message, messageObj.sender, messageObj.sentByMe, messageObj.date);

        // Show chat pane also setting buddy name in tag attribute
        this.showBuddyChat(true, buddy);

        // Focus on message input
        this.buddyChatPanel.setFocus();
    }
    
    /**
     * Update buddy chat panel based on the state of the buddy the current user is chatting with.
     */
    setBuddyChatPanelState(buddy)
    {
        // Nickname
        const newBuddyDisplayName = buddy.displayName;

        // Get current name displayed in chat
        const currBuddyDisplayName = this.buddyChatPanel.getAttribute('with');

        if (newBuddyDisplayName != currBuddyDisplayName)
        {
            this.buddyChatPanel.printSystemMessage(`${currBuddyDisplayName} is now known as ${newBuddyDisplayName}`);
            this.buddyChatPanel.setAttribute('with', newBuddyDisplayName);
        }

        // Enable/disable message input
        this.buddyChatPanel.setAttribute('disabled', !buddy.isOnline || buddy.isBlocked);
    }

    updateUnreadBuddyChatsTabCounter()
    {
        let value = BuddyChatHistoryManager.getUnreadChatsCount();

        // Set value
        this.view.querySelector('#unreadBuddyChatsCnt').innerText = value;

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

    updateUnreadBuddyMsgTabCounter(forceReset = false)
    {
        const counterNode = this.view.querySelector('#unreadBuddyMsgCnt');

        let value = 0;

        // If buddy chat is visible, always set number of unread messages to zero, otherwise increase current value
        const isChatVisible = this.buddyChatPane.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('#unreadBuddyMsgContainer').hidden = (value == 0);
    }

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

    /**
     * On Logout button click, disconnect from SmartFoxServer.
     * This causes the SmartFox listeners added by this scene to be removed (see BaseController.destroy method)
     * and the Login scene to be loaded (see Application.onConnectionLost listener).
     */
	onLogoutButtonClick(e)
	{
        // Reset buddy chat history
        BuddyChatHistoryManager.resetAllHistory();

		// Disconnect from SmartFoxServer
        this.sfs.disconnect();
	}

    /**
     * On New Game button click, create and join a new game Room.
     */
    onNewGameButtonClick(e)
    {
        // Configure Room
        const settings = new RoomSettings(this.sfs.mySelf.name + "'s game");
        settings.groupId = LobbyController.GAME_ROOMS_GROUP_NAME;
        settings.isGame = true;
        settings.maxUsers = 2;
        settings.maxSpectators = 10;

        // Request Room creation to server
        this.sfs.send(new CreateRoomRequest(settings, true));
    }

    /**
     * On Play or Watch button click in Game List, join an existing game Room as a player or Spectator respectively.
     */
    onJoinGameClickEvent(e)
    {
        // Join game Room
        this.sfs.send(new JoinRoomRequest(e.detail.roomId, null, null, e.detail.asSpectator));
    }

    /**
     * On Add buddy form submit, send request to add buddy to user's Buddy List.
     */
    onAddBuddyFormSubmit(e)
    {
        e.preventDefault();

        if (this.buddyNameInput.value != '')
        {
            // Request buddy adding to buddy list
            this.sfs.send(new AddBuddyRequest(this.buddyNameInput.value));

            // Reset buddy name input
            this.buddyNameInput.value = '';
            this.buddyNameInput.focus();
        }
    }

    /**
     * On Chat button click in Buddy List item, initialize and show chat panel.
     */
    onBuddyChatClickEvent(e)
    {
        const buddyName = e.detail.buddyName;

        // Skip if chat is already active with the same buddy
        if (this.buddyChatPane.dataset.buddyName != buddyName)
        {
            // Get chat history (if any) and reset new messages counter
            const buddyChatMessages = BuddyChatHistoryManager.getBuddyChatMessages(buddyName);
            BuddyChatHistoryManager.resetUnreadMessagesCount(buddyName);

            // Initialize and show panel
            this.initBuddyChatPanel(this.sfs.buddyManager.getBuddyByName(buddyName), buddyChatMessages);

            // Move buddy list item to top of the list and reset new messages counter
            this.buddyList.moveListItemToTop(buddyName);
            this.buddyList.setItemChatMsgCounter(buddyName, 0);
        }
    }

    /**
     * On Block/Unblock button click in Buddy List item, send request to block/unblock buddy in user's Buddy List.
     */
    onBuddyBlockClickEvent(e)
    {
        const buddyName = e.detail.buddyName;
        const isBlocked = this.sfs.buddyManager.getBuddyByName(buddyName).isBlocked;

        // Request buddy block/unblock
        this.sfs.send(new BlockBuddyRequest(buddyName, !isBlocked));
    }

    /**
     * On Remove button click in Buddy List item, send request to remove buddy from user's Buddy List.
     */
    onBuddyRemoveClickEvent(e)
    {
        const buddyName = e.detail.buddyName;

        // Request buddy removal from buddy list
		this.sfs.send(new RemoveBuddyRequest(buddyName));
    }

    /**
     * On Add button click in Buddy List item, send request to add a temporary buddy to user's Buddy List.
     */
    onBuddyAddClickEvent(e)
    {
        const buddyName = e.detail.buddyName;

        // Request buddy removal from buddy list
		this.sfs.send(new AddBuddyRequest(buddyName));
    }

    /**
     * On custom event fired by Profile Configurator control, toggle user online state in Buddy List system.
     */
    onOnlineToggleChangeEvent(e)
    {
        const goOnline = e.detail.goOnline;

        // Request online/offline state toggle
		this.sfs.send(new GoOnlineRequest(goOnline));
    }

    /**
     * On custom event fired by Profile Configurator control/s, set user's Buddy Variables.
     */
    onBuddySettingChangeEvent(e)
    {
        const varName = e.detail.variable;
        const value = e.detail.value;
        const type = value == null || value == '' ? VariableType.NULL : (typeof e.detail.value == 'number' ? VariableType.INT : VariableType.STRING);

        const buddyVars = new Array();
        buddyVars.push(new SFSBuddyVariable(varName, value, type));

        // Set Buddy Variables
        this.sfs.send(new SetBuddyVariablesRequest(buddyVars));
    }

    onBuddyChatTabShow(e)
    {
        this.updateUnreadBuddyMsgTabCounter();
        this.updateUnreadBuddyChatsTabCounter();
    }

    onBuddyChatPanelCloseClick(e)
    {
        this.showBuddyChat(false);
    }

    onBuddyChatPanelMsgSubmit(e)
    {
        const buddyName = this.buddyChatPanel.dataset.buddyName;
        const message = e.detail.message;

        // Add a custom parameter containing the recipient name
        const params = new SFSObject();
        params.putString('recipient', buddyName);

        // Retrieve buddy
        const buddy = this.sfs.buddyManager.getBuddyByName(buddyName);

        // Send message to buddy
        this.sfs.send(new BuddyMessageRequest(message, buddy, params));
    }

    //----------------------------------------------------------
    // SmartFoxServer event listeners
    //----------------------------------------------------------
    
    onRoomCreationError(evtParams)
    {
        // Show warning modal
        this.app.showWarningModal(`Game Room creation failed.\n${evtParams[EventParam.ErrorMessage]}.`);
    }

    onRoomAdded(evtParams)
    {
        const room = evtParams[EventParam.Room];

        // Add game list item
        this.gameList.addListItem(room);
    }

    onRoomRemoved(evtParams)
    {
        const room = evtParams[EventParam.Room];

        // Remove game list item
        this.gameList.removeListItem(room.id);
    }

    onUserCountChanged(evtParams)
    {
        const room = evtParams[EventParam.Room];

        // Update game list item
        this.gameList.setItemState(room);
    }

    onRoomJoin(evtParams)
    {
        // Set state to "Away" in Buddy List system
        if (this.sfs.buddyManager.myOnlineState)
        {
            const buddyVars = new Array();
            buddyVars.push(new SFSBuddyVariable(ReservedBuddyVariables.BV_STATE, 'Away', VariableType.STRING));
            this.sfs.send(new SetBuddyVariablesRequest(buddyVars));
        }

        // Go to game view
        this.app.goToView('game');
    }

    onRoomJoinError(evtParams)
    {
        // Show warning modal
        this.app.showWarningModal(`Room join failed.\n${evtParams[EventParam.ErrorMessage]}.`);
    }
    
    onBuddyListInit(evtParams)
    {
        // Initialize buddy-related entities
        this.initializeBuddyClient();
    }

    onBuddyError(evtParams)
    {
        // Show warning modal
        this.app.showWarningModal(`Buddy list system error.\n${evtParams[EventParam.ErrorMessage]}.`);
    }

    onBuddyOnlineStateChange(evtParams)
    {
        const buddy = evtParams[EventParam.Buddy];
        const isItMe = evtParams[EventParam.IsItMe];

        // As this event is fired in case of online state update for both the current user and their buddies,
        // we have to check who the event refers to

        if (!isItMe)
            this.updateBuddyListEntry(buddy);
        else
        {
            this.displayUserStateAsBuddy();

            const isOnline = this.sfs.buddyManager.myOnlineState;

            // Show/hide buddy list
            this.showBuddyList(isOnline);

            if (!isOnline)
            {
                // Hide chat if current user went offline
                this.showBuddyChat(false);
            }
            else
            {
                // Update all buddy items if current user came online
                for (let b of this.sfs.buddyManager.buddyList)
                    this.updateBuddyListEntry(b);
            }
        }
    }

    onBuddyVariablesUpdate(evtParams)
    {
        const buddy = evtParams[EventParam.Buddy];
        const isItMe = evtParams[EventParam.IsItMe];

        // As this event is fired in case of Buddy Variables update for both the current user and their buddies,
        // we have to check who the event refers to

        if (!isItMe)
            this.updateBuddyListEntry(buddy);
        else
            this.displayUserStateAsBuddy();
    }

    onBuddyBlock(evtParams)
    {
        const buddy = evtParams[EventParam.Buddy];

        this.updateBuddyListEntry(buddy);

        // Reset unread messages counter and update counter in buddy list tab
        BuddyChatHistoryManager.resetHistory(buddy.name);
        this.updateUnreadBuddyChatsTabCounter();
    }

    onBuddyRemove(evtParams)
    {
        const buddy = evtParams[EventParam.Buddy];

        this.buddyList.removeListItem(buddy.name);

        if (this.buddyChatPanel.dataset.buddyName == buddy.name)
            this.showBuddyChat(false);

        // Reset unread messages counter and update counter in buddy list tab
        BuddyChatHistoryManager.resetHistory(buddy.name);
        this.updateUnreadBuddyChatsTabCounter();
    }

    onBuddyAdd(evtParams)
    {
        const buddy = evtParams[EventParam.Buddy];

        // Add buddy list item at the top of the list
        this.buddyList.addListItem(buddy, true);
    }

    onBuddyMessage(evtParams)
    {
        const sender = evtParams[EventParam.Buddy];
        const isItMe = evtParams[EventParam.IsItMe];
        const message = evtParams[EventParam.Message];
        const recipient = evtParams[EventParam.Data].getString('recipient');

        const targetBuddyName = isItMe ? recipient : sender.name;
        let senderDisplayName;
        
        if (isItMe)
            senderDisplayName = (this.sfs.buddyManager.myNickname ? this.sfs.buddyManager.myNickname : this.sfs.mySelf.name);
        else
            senderDisplayName = sender.nickname ? sender.nickname : sender.name;

        // Add message to queue
        const chatMsg = BuddyChatHistoryManager.addMessage(targetBuddyName, senderDisplayName, isItMe, message);

        // Show message or increase message counter
        if (this.buddyChatPanel.dataset.buddyName == chatMsg.target)
        {
            // Display message in chat panel
            this.buddyChatPanel.printChatMessage(chatMsg.message, chatMsg.sender, chatMsg.sentByMe, chatMsg.date);

            // On smaller screens, the active tab could be different from the buddy chat one
            // In this case, show the unread messages counter
            this.updateUnreadBuddyMsgTabCounter();
        }
        else
        {
            // Increase unread messages count
            // NOTE: there's no need to make sure the sender is not the current user,
            // as in this example the current user can't send buddy messages in other ways than
            // the chat panel (which would make the above if statement true)
            const unreadMsgCnt = BuddyChatHistoryManager.increaseUnreadMessagesCount(chatMsg.target);

            // Update buddy list item
            this.buddyList.setItemChatMsgCounter(chatMsg.target, unreadMsgCnt);
        }

        // On smaller screens, the active tab could be different from the buddy list one
        // In this case, show the unread chats counter
        this.updateUnreadBuddyChatsTabCounter();
    }
}
