import BaseController from './base-controller.js';
import ProfileConfigurator from '../components/profile-configurator.js';
import GameList from '../components/game-list.js';
import { SFSEvent, EventParam } from 'sfs3-api';
import { RoomSettings, CreateRoomRequest, JoinRoomRequest } from 'sfs3-api';

export default class LobbyController extends BaseController
{
    static GAME_ROOMS_GROUP_NAME = 'games';

    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');
    }

    //----------------------------------------------------------
    // 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 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);

        // 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);

        // 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 listener to join button click event fired by GameList class
        this.gameList.removeEventListener(GameList.JOIN_CLICK_EVT, this.boundOnJoinGameClickEvent);

        // Reset game list
        this.gameList.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);
        }
    }

    //----------------------------------------------------------
    // 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)
	{
		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));
    }

    //----------------------------------------------------------
    // 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)
    {
        // Go to game view
        this.app.goToView('game');
    }

    onRoomJoinError(evtParams)
    {
        // Show warning modal
        this.app.showWarningModal(`Room join failed.\n${evtParams[EventParam.ErrorMessage]}.`);
    }
}
