using Godot;

using Sfs3.Client.Core;
using Sfs3.Client.Requests;
using Sfs3.Client.Entities;
using System.Collections.Generic;

using System.Linq;
using System;

/**
 * Script attached to the main node in the scene.
 */
public partial class LobbyController : BaseController
{ 
    private const string GAME_ROOMS_GROUP_NAME = "games";
    private const string EXTENSION_ID = "Shooter";
    private const string EXTENSION_CLASS = "sfs3.extensions.examples.shooter.ShooterExtension";

    //----------------------------------------------------------
    // UI elements
    //----------------------------------------------------------
    [ExportCategory("UI Settings")]

    [Export]
    public ProfileConfigurator profileConfigurator;
	[Export]
	public PopupDialog warningPanel;
    [Export]
    public Label warningLabel;
    [Export]
    public GameList gameList;

    //----------------------------------------------------------
    // Callback methods
    //----------------------------------------------------------
    #region
    public override void _Ready()
    {
        base._Ready();
        
        sfs = Global.GetSfsClient();

        // Add SFS event listeners
        AddSmartFoxListeners();

        // Add listener to join button click event fired by GameList class
        gameList.JoinGameAction = OnJoinGamePressed;

        // Populate list of available games
        var rooms = sfs.RoomManager.GetRoomList();
        gameList.PopulateList(rooms);

        // Display user name in profile modal
        profileConfigurator.DisplayUserName(sfs.MySelf.Name);
    }
    #endregion

    //----------------------------------------------------------
    // UI event listeners
    //----------------------------------------------------------
    #region
    
    public void OnLogoutButtonClick()
    {
        sfs.Disconnect();
    }

    /**
     * On New Game button click, create and join a new game Room.
     */
    public void OnNewGameButtonClick()
    {
        // Configure Room
        RoomSettings settings = new(sfs.MySelf.Name + "'s game")
        {
            GroupId = GAME_ROOMS_GROUP_NAME,
            IsGame = true,
            MaxUsers = 4,
            MaxSpectators = 0,
            Extension = new RoomExtension(EXTENSION_ID, EXTENSION_CLASS)
        };

        // Request Room creation to server
        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.
     */
    public void OnJoinGamePressed(int roomId, bool asSpectator)
    {
        sfs.Send(new JoinRoomRequest(roomId, null, null, asSpectator));
    }
    #endregion

    //----------------------------------------------------------
    // Helper methods
    //----------------------------------------------------------
    #region
    private void AddSmartFoxListeners()
    {
        sfs.AddEventListener(SFSEvent.ROOM_CREATION_ERROR, OnRoomCreationError);
        sfs.AddEventListener(SFSEvent.ROOM_ADD, OnRoomAdded);
        sfs.AddEventListener(SFSEvent.ROOM_REMOVE, OnRoomRemoved);
        sfs.AddEventListener(SFSEvent.USER_COUNT_CHANGE, OnUserCountChanged);
        sfs.AddEventListener(SFSEvent.ROOM_JOIN, OnRoomJoin);
        sfs.AddEventListener(SFSEvent.ROOM_JOIN_ERROR, OnRoomJoinError);
    }

    public override void RemoveSmartFoxListeners()
    {
        if (sfs != null)
        {
            sfs.RemoveEventListener(SFSEvent.ROOM_CREATION_ERROR, OnRoomCreationError);
            sfs.RemoveEventListener(SFSEvent.ROOM_ADD, OnRoomAdded);
            sfs.RemoveEventListener(SFSEvent.ROOM_REMOVE, OnRoomRemoved);
            sfs.RemoveEventListener(SFSEvent.USER_COUNT_CHANGE, OnUserCountChanged);
            sfs.RemoveEventListener(SFSEvent.ROOM_JOIN, OnRoomJoin);
            sfs.RemoveEventListener(SFSEvent.ROOM_JOIN_ERROR, OnRoomJoinError);
        }
    }
    #endregion

    //----------------------------------------------------------
    // SmartFoxServer event listeners
    //----------------------------------------------------------
    #region
    private void OnRoomCreationError(ApiEvent evt)
    {
        // Show warning
        warningLabel.Text = String.Format("Game Room creation failed.\n{0}.", evt.Params[EventParam.ErrorMessage]);
        warningPanel.Show();
    }

    private void OnRoomAdded(ApiEvent evt)
    {
        Room room = (Room)evt.Params[EventParam.Room];

        // Display game list item
        gameList.AddListItem(room);
    }

    public void OnRoomRemoved(ApiEvent evt)
    {
        Room room = (Room)evt.Params[EventParam.Room];

        // Remove game list item
        gameList.RemoveListItem(room.Id);
    }

    public void OnUserCountChanged(ApiEvent evt)
    {
        Room room = (Room)evt.Params[EventParam.Room];
        
        // Update game list item
        gameList.SetItemState(room.Id);
    }

    private void OnRoomJoin(ApiEvent evt)
    {
        // Load game scene
        GetTree().ChangeSceneToFile("scenes/Game.tscn");
    }

    private void OnRoomJoinError(ApiEvent evt)
    {
         // Show warning
        warningLabel.Text = String.Format("Room join failed.\n{0}.", evt.Params[EventParam.ErrorMessage]);
        warningPanel.Show();
    }
    #endregion
}