import BaseController from './base-controller.js';
import ProfileConfigurator from '../components/profile-configurator.js';
import AssetManager from '../managers/asset-manager.js';
import { SFSEvent, EventParam } from 'sfs3-api';
import { 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.stage = null;
    }

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

    initialize()
    {
        super.initialize();

        AssetManager.onBackgroundsLoadCompleteCallback = () => { this.onMapBackgroundsLoadComplete(); }

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

        // Add SFS event listeners
        this.sfs.addEventListener(SFSEvent.ROOM_JOIN, this.onRoomJoin, this);
        this.sfs.addEventListener(SFSEvent.ROOM_JOIN_ERROR, this.onRoomJoinError, this);

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

        // Display room selector
        this.initRoomSelector();

        // Show view
        this.showView();
    }

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

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

        // Clear stage
        this.stage.removeAllChildren();
        this.stage.enableMouseOver(0);
        this.stage.removeAllEventListeners();

    }

    removeSmartFoxListeners()
    {
        if (this.sfs != null)
        {
            this.sfs.removeEventListener(SFSEvent.ROOM_JOIN, this.onRoomJoin);
            this.sfs.removeEventListener(SFSEvent.ROOM_JOIN_ERROR, this.onRoomJoinError);
        }
    }

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

    initRoomSelector()
    {
        // Setup stage
		this.stage = new createjs.Stage('roomSelector');

        // For each MMORoom, retrieve the map setup data from a dedicated global Room Variable
        // and for each static map item listed in the configuration create:
        // - a sprite to be cloned and placed on the map later
        // - a list of tuples containing the coordinates where to place the sprite clones later
        // For each Room also save a list of access point coordinates

        const bgLoaderManifest = [];

        for (let room of this.sfs.roomManager.getRoomList())
        {
            // STATIC MAP ITEMS

            const setupObj = room.getVariable('mapItems').value; // SFSObject
            AssetManager.buildStaticMapItems(room.id, setupObj);

            // MAP BACKGROUND

            const mapName = room.name.toLowerCase().replace(/ /g, '-');

            bgLoaderManifest.push(
                {id: room.name, src:'assets/images/' + mapName + '-background.jpg'}
            )
        }

        // Load maps backgrounds
        AssetManager.loadMapBackgrounds(bgLoaderManifest);
    }

    onMapBackgroundsLoadComplete()
    {
        this.app.trace('Map backgrounds loading completed');

        // Display minimaps for Room selection
		this.showMinimaps();
    }

    /**
	 * Creates a minimap on stage for each joinable Room.
	 * To make it look like the actual map, static items (trees) are placed on the minimap too.
	 */
	showMinimaps()
	{
        const MINIMAP_WIDTH = 280;
        const MINIMAP_HEIGHT = 148;
        const MINIMAP_SEP = 20;
        
        const roomsCount = this.sfs.roomManager.roomCount;

		// Set canvas size based on the number of Rooms
		this.stage.canvas.width = (MINIMAP_WIDTH * roomsCount) + (MINIMAP_SEP * (roomsCount - 1));
		this.stage.canvas.height = MINIMAP_HEIGHT;

        // Loop through the Room list
        for (let r = 0; r < roomsCount; r++)
		{
            const room = this.sfs.roomManager.getRoomList()[r];

            // Retrieve list of static map items
			const mapItems = AssetManager.getStaticMapItems(room.id);

			// Create minimap container
			const minimapContainer = new createjs.Container();

			// Add background bitmap
			const bg = new createjs.Bitmap(AssetManager.bgLoader.getResult(room.name));
			minimapContainer.addChild(bg);

            // Create a shape to apply rounded corners
            const roundedShape = new createjs.Shape();
            roundedShape.graphics
                .beginFill('#000')
                .drawRoundRect(0, 0, bg.image.width, bg.image.height, bg.image.width / 100 * 5); // 10% corner radius

            // Mask container to round corners
            bg.mask = roundedShape;

			// Add static map items cloning the sprites created previously
			for (let itemId in mapItems)
			{
				for (var i = 0; i < mapItems[itemId].coordinates.length; i++)
				{
					const coords = mapItems[itemId].coordinates[i];
					const sprite = mapItems[itemId].sprite.clone();

					sprite.x = coords[0];
					sprite.y = coords[1];

					minimapContainer.addChild(sprite);
				}
			}

			// Scale minimap
			minimapContainer.setTransform((MINIMAP_WIDTH + MINIMAP_SEP) * r, 0, 0.2, 0.2);

			// Add reference to Room name
			minimapContainer.sfsRoomName = room.name;

			// Add minimap click listener
			minimapContainer.addEventListener('click', (e) => { this.onMinimapClick(e); });
			minimapContainer.cursor = 'pointer';

			// Add minimap to stage
			this.stage.addChild(minimapContainer);
			this.stage.enableMouseOver();
		}

		this.stage.update();
	}

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

	/**
	 * Mini map click handler.
	 * Performs the MMORoom join.
	 */
	onMinimapClick(e)
	{
		// Join selected MMORoom
		this.sfs.send(new JoinRoomRequest(e.currentTarget.sfsRoomName));
	}

    //----------------------------------------------------------
    // SmartFoxServer event listeners
    //----------------------------------------------------------
    
    onRoomJoin(evtParams)
    {
        this.app.trace("Room joined: " + evtParams[EventParam.Room]);

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

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