import { _decorator, game, Node } from 'cc';
import { GameOverPanel } from '../../../UI/in-game-panel/GameOverPanel';
import { HUDPanel } from '../../../UI/in-game-panel/HUDPanel';
import { MESSAGE_TYPE, MessagePanel } from '../../../UI/global/MessagePanel';
import { LevelCompletePanel } from '../../../UI/in-game-panel/LevelCompletePanel';
import { EventArgs, IEventsData, IExitHandler } from '../interface/IPrimary';
import { Cards_Constants } from '../../../constants/Cards_Constants';
import { PopupManager } from './PopupManager';
import { PopupType } from '../../../UI/popup/PopupType';
import { UIPanel } from '../../../UI/base/UIPanel';
import { ManagerType, TopLevelManager } from '../data-flow/TopLevelManager';
import { MainManager } from '../data-flow/MainManager';
import { GameManager } from '../state/GameManager';
import { GameSettingsManager } from '../data-flow/settings/GameSettingsManager';
import { IGameDataSaver, ISaveInfoConnector } from '../interface/ISaveInfo';
import { MenuSettingsPanel } from '../../../UI/menu/MenuSettingsPanel';

const { ccclass, property } = _decorator;

@ccclass('UIManager')
export class UIManager extends TopLevelManager implements IExitHandler, IEventsData, ISaveInfoConnector
{
    @property({type: MainManager, serializable: false})
    public MainManager: MainManager;

    private gameManager: GameManager;
    private gameSettingsManager: GameSettingsManager;

    @property({type: Node})
    public m_StartMenuPanel: Node;

    @property({type: Node})
    public m_GameOverPanel: Node;

    @property({type: Node})
    public m_SettingsPanel: Node;
    
    @property({type: MessagePanel})
    public m_MessagePanel: MessagePanel;
    
    @property({type: Number})
    private m_StartPanelDisplayDelay: number = 0.5;
    
    private HUDPanelComp: HUDPanel;

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

    private fn_SetGameManager()
    {
        this.gameManager = this.gameManager == null ? this.MainManager.fn_GetMainManager<GameManager>(ManagerType.GAME) : this.gameManager;
    }

    public fn_PassEventData(evtArgs: EventArgs) 
    {
        this.gameManager.fn_PassEventData(evtArgs);
    }

    public fn_LoadSavedData<T>(type: ManagerType) : any
    {
        let topLevelManager = this.MainManager.fn_GetMainManager<T>(type);

        // let castManager = topLevelManager as T;
        // let castedManager = castManager as ISaveInfo; // could throw error

        // for example we are casting GameSettingsManager to IGameDataSaver
        let castedManager = topLevelManager as IGameDataSaver; // could throw error
        if (castedManager != null)
        {
            console.log("found Casted manager");

            return castedManager.fn_LoadSavedData();
        }
        else 
        {
            console.log("Casted manager is null");
        }

        return null;
    }

    public fn_SaveNewData<T>(data: any, type: ManagerType) 
    {
        let topLevelManager = this.MainManager.fn_GetMainManager<T>(type);

        // let castManager = topLevelManager as T;
        // let castedManager = castManager as ISaveInfo; // could throw error

        let castedManager = topLevelManager as IGameDataSaver; // could throw error
        if (castedManager != null)
        {
            castedManager.fn_SaveNewData(data);
        }
    }

    public fn_PassSettingsInfo(data: any)
    {
        this.gameSettingsManager = this.gameSettingsManager == null ? 
                                    this.MainManager.fn_GetMainManager<GameSettingsManager>(ManagerType.GAME_SETTINGS) : this.gameSettingsManager;
        this.gameSettingsManager.fn_SetSettingsData(data);
    }

    public fn_ShowPanel(): void 
    {
        this.fn_ShowStartPageAfterDelay();
    }

    public fn_Execute(): void 
    {
        this.fn_OnReturnToMenu();
    }

    public fn_OnReturnToMenu(): void 
    {
        this.fn_SetInGameHUDState(false);
        this.fn_ShowStartPageAfterDelay();
    }

    public fn_Init() 
    {
        console.log("Init");

        // this.fn_UpdateMatchesHUD(0);
        // this.fn_UpdateTurnsHUD(0);
        
        this.fn_SetGameManager();
        
        PopupManager.m_GetInstance.fn_DeactivateAllPanels();
        PopupManager.m_GetInstance.fn_ActivatePanel(PopupType.PT_Hud);

        this.fn_HideHintHUD();
        this.fn_SetHudPanelComp();
    }
        
    public fn_InitAllPanels() 
    {
        let popupManagerInst = PopupManager.m_GetInstance;

        for (let idx = 0; idx < popupManagerInst.fn_PanelsCount; idx++)
            popupManagerInst.fn_IteratePanelFromMap(idx).fn_InitUIManager(this);

        this.fn_ActivatePanel(PopupType.PT_MainMenu);
    }

    private fn_ShowStartPageAfterDelay()
    {
        this.fn_DeactivateCurrentActivePanel();
        setTimeout(() => 
        {
            this.fn_ActivatePanel(PopupType.PT_MainMenu);
        }, Cards_Constants.MILLI_SEC * this.m_StartPanelDisplayDelay);
    }

    public fn_GetUIPanelComp<T extends UIPanel>(popupType: PopupType) : T
    {
        return (PopupManager.m_GetInstance.fn_GetPanelFromMap(popupType))  as T;
    }

    public fn_GetHudPanelComp() : HUDPanel
    {
        if (this.fn_SetHudPanelComp())
            return this.HUDPanelComp;
        
        return null;
    }

    public fn_SetHudPanelComp() : boolean
    {
        if (this.HUDPanelComp) return true;

        this.HUDPanelComp = this.fn_GetUIPanelComp<HUDPanel>(PopupType.PT_Hud);
        return this.HUDPanelComp != null;
    }

    public fn_InitHUDInfo(pairs: number, tries: number)
    {
        if (this.fn_SetHudPanelComp())
            this.HUDPanelComp.fn_InitInfo(pairs, tries);
    }

    public fn_UpdateMatchesHUD(matchesCount: number)
    {
        if (this.fn_SetHudPanelComp())
            this.HUDPanelComp.fn_UpdateMatchesLabel(matchesCount);
    }
    
    public fn_UpdateTurnsHUD(turnsCount: number)
    {
        if (this.fn_SetHudPanelComp())
            this.HUDPanelComp.fn_UpdateTurnsLabel(turnsCount);
    }
    
    public fn_SetGameOverMsg()
    {
        let panel = this.fn_GetUIPanelComp<GameOverPanel>(PopupType.PT_GameOver);
        if (this.fn_GetUIPanelComp<GameOverPanel>(PopupType.PT_GameOver))
            panel.fn_InitText();
    }

    public fn_SetInGameHUDState(state: boolean)
    {
        if (state)
            this.fn_ActivatePanel(PopupType.PT_Hud);
        else
        {
            let hudPanel = PopupManager.m_GetInstance?.fn_GetPanelFromMap(PopupType.PT_Hud) as HUDPanel;
            if (hudPanel)
                hudPanel.fn_PlayHudDropUpAnim();
            
            PopupManager.m_GetInstance?.fn_DeactivateSpecificPanel(PopupType.PT_Hud);
        }
}

    public fn_ShowHintHUD(state: boolean)
    {
        if (this.fn_SetHudPanelComp())
            this.HUDPanelComp.fn_ShowHintBar(state);
    }

    public fn_HideHintHUD()
    {
        if (this.fn_SetHudPanelComp())
            this.HUDPanelComp.fn_HideHintBar();
    }

    public fn_ShowMessagePanel(type: MESSAGE_TYPE) 
    {
        this.m_MessagePanel.fn_InitMessageText(type);
    }

    public fn_InitLevelCompletePanel(matches: number, turns: number, currentLvl: number, nextLvl: number)
    {
        let panel = this.fn_GetUIPanelComp<LevelCompletePanel>(PopupType.PT_LevelComplete);
        if (panel)
            panel.fn_InitLevelData(matches, turns, currentLvl, nextLvl);
    }

    public fn_ActivatePanel(type: PopupType)
    {
        PopupManager.m_GetInstance?.fn_ActivatePanel(type);
    }

    public fn_DeactivateCurrentActivePanel()
    {
        // console.log("::: fn_DeactivatePanel: " + PopupManager.m_GetInstance.fn_GetActivePanel.node.name);
        PopupManager.m_GetInstance?.fn_DeactivatePanel();
    }

    public fn_DeactivateSpecificPanel(type: PopupType)
    {
        PopupManager.m_GetInstance?.fn_DeactivateSpecificPanel(type);
    }

    public fn_OnQuitGameClicked()
    {
        this.fn_SetGameManager();
        this.gameManager.fn_QuitGame();
    }

    public fn_OnNextLevelClicked()
    {
        this.gameManager.fn_OnNextLevelClicked();
    }

    public fn_UpdateLevelsPage()
    {
        this.gameManager.fn_UpdateLevelsPage();
    }

    public fn_InitMenuSettingsData(data: any)
    {
        let menuSettingsPanel = this.fn_GetUIPanelComp<MenuSettingsPanel>(PopupType.PT_MenuSettings);
        menuSettingsPanel.fn_InitSettingsData(data);
    }
}

