import { _decorator, ccenum, Component, game, Node } from 'cc';
import { ManagerType, TopLevelManager } from '../data-flow/TopLevelManager';
import { EventArgs, EventsType, IEventsData, IRestartHandler } from '../interface/IPrimary';
import { EventsHandler } from '../data-flow/events/EventsHandler';
import { UIManager } from '../ui/UIManager';
import { GridManager } from '../../in-game/board/GridManager';
import { CardManager } from '../../in-game/board/CardManager';
import { LevelManager } from '../data-flow/LevelManager';
import { MainManager } from '../data-flow/MainManager';
import { Cards_Constants } from '../../../constants/Cards_Constants';
import { UserDataBehaviour } from '../../data/UserDataBehaviour';
import { LevelCompletePanel } from '../../../UI/in-game-panel/LevelCompletePanel';
import { PopupType } from '../../../UI/popup/PopupType';
import { MESSAGE_TYPE } from '../../../UI/global/MessagePanel';


const { ccclass, property } = _decorator;

export enum GAME_STATE
{
    GS_INITAL_INIT,
    GS_IN_GAME,
    GS_ON_LEVEL_COMPLETE,
    GS_GAME_OVER,
    GS_GAME_FINISH
}
ccenum(GAME_STATE);

@ccclass('GameManager')
export class GameManager extends TopLevelManager implements IEventsData, IRestartHandler
{
    @property({type: EventsHandler})
    public eventsHandler: EventsHandler;

    @property({type: UIManager})
    public m_UIManager: UIManager;

    @property({type: GridManager})
    public m_GridManager: GridManager;

    @property({type: CardManager})
    public m_CardManager: CardManager;

    @property({type: LevelManager})
    public m_LevelManager: LevelManager;

    @property({type: GAME_STATE})
    public m_GameState: GAME_STATE = GAME_STATE.GS_INITAL_INIT;

    @property({type: Number})
    public m_GameEndPanelDelay: number = 1;

    @property({type: Number})
    public m_LevelCompleteDelay: number = 1;

    public mainManager: MainManager;

    public fn_InitMainManager(mainManager: MainManager) 
    {
        this.mainManager = mainManager;
        this.eventsHandler.fn_InitGameManager(this);
    }

    public fn_Execute(evtType: EventsType): void 
    {
        switch (evtType)
        {
            case EventsType.RESTART:
                this.fn_OnRestartGameRequest();
                break;
        }
    }

    public fn_InitManagers()
    {
        this.m_LevelManager.fn_InitGridManager(this.m_GridManager);
    }

    public fn_OnRestartGameRequest() 
    {
        this.m_UIManager.fn_DeactivateCurrentActivePanel();
        this.m_CardManager.fn_SaveCardData(true);
        this.m_UIManager.fn_GetHudPanelComp().fn_SetSettingsBtnState(true);
        this.fn_OnGameStateChange(GAME_STATE.GS_IN_GAME);
    }

    public fn_PassEventData(evtArgs: EventArgs)
    {
        this.eventsHandler.fn_ManageEventOperation(evtArgs.evtOp, evtArgs.evtType);
    }

    public fn_InitState()
    {
        this.OnGameInit();
    }

    public fn_Initialize(): void 
    {
        this.fn_OnGameStateChange(GAME_STATE.GS_INITAL_INIT);
        this.fn_OnGameStart();
    }
    
    private OnGameInit() 
    {
        this.fn_OnGameStateChange(GAME_STATE.GS_INITAL_INIT);
    }

    public fn_OnNextLevelClicked()
    {
        this.fn_UpdateLevelsPage();
        this.m_UIManager.fn_DeactivateCurrentActivePanel();
        this.m_UIManager.fn_GetHudPanelComp().fn_SetSettingsBtnState(true);
        this.fn_OnGameStart();
    }

    public fn_OnGameStart()
    {
        this.fn_OnGameStateChange(GAME_STATE.GS_IN_GAME);
    }
    
    public fn_OnGameOver()
    {
        this.fn_OpenGameEndPanel(GAME_STATE.GS_GAME_OVER);
    }

    public fn_OnGameFinished()
    {
        this.fn_OpenGameEndPanel(GAME_STATE.GS_GAME_FINISH);
    }

    /**
     * Summary
     * Opens game over panel or game finish panel at the end
     */
    private fn_OpenGameEndPanel(gameState: GAME_STATE)
    {
        this.m_UIManager.fn_GetHudPanelComp().fn_SetSettingsBtnState(false);
        
        setTimeout(() => {
            this.fn_OnGameStateChange(gameState);
        }, Cards_Constants.MILLI_SEC * this.m_GameEndPanelDelay);
    }

    public fn_OnLevelCompleted()
    {
        if (this.m_LevelManager.fn_GetCurrentLevelNum() === this.m_LevelManager.fn_GetLastLevelNum())
        {
            // do something
            this.fn_OnGameFinished();
        }
        else 
        {
            this.fn_OnGameStateChange(GAME_STATE.GS_ON_LEVEL_COMPLETE);
        }
    }

    private fn_OnGameStateChange(gameState: GAME_STATE)
    {
        this.m_GameState = gameState;
        console.log("OnGameStateChange: " + this.m_GameState.toString());
        switch (this.m_GameState)
        {
            case GAME_STATE.GS_INITAL_INIT:
                this.fn_DisableHUD();
                this.m_UIManager.fn_InitAllPanels();

                let userDataBehaviour = this.mainManager.fn_GetMainManager<UserDataBehaviour>(ManagerType.USER_DATA_BEHAVIOUR);
                // userDataBehaviour.saveManager.fn_SubscribeForWindowCloseEvent(() => 
                // {
                //     this.m_CardManager.fn_SaveCardData();
                // });
                break;

            case GAME_STATE.GS_IN_GAME:
                this.fn_StartGame();
                break;
            
            case GAME_STATE.GS_ON_LEVEL_COMPLETE:
                this.m_UIManager.fn_GetHudPanelComp().fn_SetSettingsBtnState(false);
                setTimeout(() => 
                {
                    this.fn_UpdateLevelData();
                }, Cards_Constants.MILLI_SEC * this.m_LevelCompleteDelay);
                break;
            
            case GAME_STATE.GS_GAME_FINISH:
                this.fn_DisableHUD();
                this.m_UIManager.fn_ActivatePanel(PopupType.PT_AllLevelsComplete);
                break;
            
            case GAME_STATE.GS_GAME_OVER:
                // this.fn_DisableHUD();
                this.m_UIManager.fn_SetGameOverMsg();
                this.m_UIManager.fn_ActivatePanel(PopupType.PT_GameOver);
                break;
        }
    }

    private fn_UpdateLevelData()
    {
        this.m_UIManager.fn_ActivatePanel(PopupType.PT_LevelComplete);
        console.log("### UpdateLevelData: Archive card in level complete panel");
        this.m_UIManager.fn_GetUIPanelComp<LevelCompletePanel>(PopupType.PT_LevelComplete).fn_ArchiveCard();

        this.m_UIManager.fn_InitLevelCompletePanel(
            this.m_CardManager.fn_GetMatchesCount(), 
            this.m_CardManager.fn_GetTurnsCount(), 
            this.m_LevelManager.fn_GetCurrentLevelNum(),
            this.m_LevelManager.fn_GetCurrentLevelNum() + 1);

        this.fn_UpdateNewUnlockedLevel();
    }
    
    private fn_UpdateNewUnlockedLevel() 
    {
        let userDataBehaviour = this.mainManager.fn_GetMainManager<UserDataBehaviour>(ManagerType.USER_DATA_BEHAVIOUR);
        let newUnlockedLevel = this.m_LevelManager.fn_GetCurrentLevelNum() + 1;
        userDataBehaviour.fn_SetLevelUnlockedData(newUnlockedLevel, newUnlockedLevel);
    }

    public fn_UpdateLevelsPage()
    {
        this.m_LevelManager.fn_UpdateLevelsDataOnLevelCompletion();
    }

    private fn_StartGame()
    {
        if (this.m_LevelManager.fn_GetLevelSelectedState())
        {
            this.m_UIManager.fn_Init();
            this.m_CardManager.fn_Init(this);
            this.m_GridManager.fn_Init();
        }
        else 
        {
            this.m_UIManager.fn_ShowMessagePanel(MESSAGE_TYPE.MT_LEVEL_SEL);
        }
    }

    public fn_DisableHUD()
    {
        this.m_UIManager.fn_SetInGameHUDState(false);
    }

    public fn_OnSettingsBtnClick()
    {
        this.m_UIManager.fn_ActivatePanel(PopupType.PT_Settings);
    }

    public fn_QuitGame()
    {
        game.end();
    }
}

