
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Linq;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using System;

namespace SimplifyXR
{

    public enum ReferenceType
    {
        bySceneOrModule, 
        byAsset
    }


    [System.Serializable]
    public class PanelReference: IModuleOrSceneReference
    {
        public string buttonLabel;
        public Sprite buttonIcon;
        public Button panelButton;
        public ReferenceType referenceType;
        public SceneOrModuleLoadType loadType;
        public UnityEngine.Object scene;
        public GameObject panelObject;
        public bool isModule;
        public string sceneKey;
        public GameObject localInstance;

        public bool IsModule()
        {
            return isModule;
        }

        public SceneOrModuleLoadType LoadType()
        {
            return loadType;
        }

        public string SceneKey()
        {
            return sceneKey;
        }
    }

    public class NavMenuFeatures : BasePanelFeatures
    {     


        [Header("Nav Menu Features")]
        public bool customizeNavMenuFeatures;

        [Conditional("customizeNavMenuFeatures",true, ComparisonType.Equals)]
        public bool autoDisplayLoginState;
        [Conditional("customizeNavMenuFeatures", true, ComparisonType.Equals)]
        public bool autoDockPanels;


        [HideInInspector]
        public List<PanelReference> navReferences;

        #region Elements

        Button mainMenuButton => baseRoot.GetElementAsType<Button>("Main Menu Button");
        Button adjustButton => baseRoot.GetElementAsType<Button>("Adjust Button");
        Button instructionButton => baseRoot.GetElementAsType<Button>("Instruction Button");
        Button referencesButton => baseRoot.GetElementAsType<Button>("References Button");
        Button metricsButton => baseRoot.GetElementAsType<Button>("Metrics Button");
        Button settingsButton => baseRoot.GetElementAsType<Button>("Settings Button");
        NavMenuDock navMenuDock => baseRoot.GetElementAsType<NavMenuDock>("Nav Menu Dock");
        LoginStateManager loginStateManager => baseRoot.GetElementAsType<LoginStateManager>("Login State Manager");

        #endregion

        private Dictionary<Button, Action> buttonActions;



        private void BuildActionDictionary()
        {
            buttonActions = new Dictionary<Button, Action>();
            navReferences.ForEach(reference =>
            {
                buttonActions.Add(reference.panelButton,
                    () => {
                        LoadPanelByReference(reference);
                    });
            });
        }


        public void Awake()
        {
            base.Awake();
            BuildActionDictionary();
            SetupNavButtonActions();         
        }

        public void Start()
        {

            if (autoDisplayLoginState) SetupLoginEventHandlers();
        }

        private void SetupLoginEventHandlers()
        {
            IdentityManager.Instance.IdentityBehavior = new AuthController();
            IdentityManager.IdentityLoaded += loginStateManager.SetLoginState;

            ((AuthController)IdentityManager.Instance.IdentityBehavior)
                ?.LoadCachedToken();
        }

        public void OnDestroy()
        {
            base.OnDestroy();
            RemoveButtonActions();

            if (autoDisplayLoginState) IdentityManager.IdentityLoaded -= loginStateManager.SetLoginState;
        }

        private void RemoveButtonActions()
        {
            buttonActions.Keys.ToList().ForEach(key => key?.onClick.RemoveAllListeners());
        }


        private void SetupNavButtonActions()
        {
            buttonActions.Keys.ToList().ForEach(key =>
            {
                key.onClick.AddListener(() => { buttonActions[key]?.Invoke(); });
            });
        }

        public GameObject LoadPanelByReference(PanelReference reference)            
        {
            var panel = StandardAssetsHelpers.FindObjectByToolboxAssetType(reference.panelObject);              
            reference.localInstance = panel ? panel.gameObject : null;

            if (reference.localInstance)
            {
                if (autoDockPanels) navMenuDock.DockItem(
                    reference.panelButton.GetComponent<NavButton>(),
                    reference.localInstance);
                if (!autoDockPanels) reference.localInstance.SetActive(true);
            }
            else
            {
                switch (reference.referenceType)
                {

                    case ReferenceType.bySceneOrModule:
                        StandardAssetsHelpers
                            .HandleModuleSceneLoading(reference);
                        break;
                    case ReferenceType.byAsset:
                        reference.localInstance =  reference.localInstance == null ? Instantiate(
                            reference.panelObject) : reference.localInstance;
                        if (autoDockPanels)  navMenuDock.DockItem(
                             reference.panelButton.GetComponent<NavButton>(),
                             reference.localInstance);
                        if (!autoDockPanels) reference.localInstance.SetActive(true);
                        break;
                }
            }
            return reference.localInstance;
        }

    }

}

