using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace XenseAR
{

    public class Instruction : MonoBehaviour
    {
        private static Instruction _instance;

        [Header("Dynamic Content")]
        [SerializeField] GameObject dynamicUI;

        [Header("Static Content")]
        [SerializeField] TMP_Text controlText;
        [SerializeField] GameObject blurBackground;
        [SerializeField] GameObject localizingIconObject;
        [SerializeField] GameObject successIconObject;
        [SerializeField] Button button;
        [SerializeField] Button guideButton;
        [SerializeField] GameObject ExitWhileScanningButton;

        Action callback;
        Action guideCallback;

        GameObject guideGameObject;
        private InstructionUI instructionUI = InstructionUI.LocalizingInstruction;

        Dictionary<string, GameObject> dynamicContent = new Dictionary<string, GameObject>();

        string guidePrefabResourceURL;

        Action hideAction = null;

        public enum InstructionUI
        {
            LocalizingInstruction,
            ScanningGuide
        }

        public enum SubNotify
        {
            Localizing,
            Success
        }

        private void Awake()
        {
            _instance = this;
            //DontDestroyOnLoad(this);
        }

        private void Start()
        {
            ExitWhileScanningButton.SetActive(true);
            button.onClick.AddListener(OnClick);
            guideButton.onClick.AddListener(OnClickGuild);
        }

        private void OnDestroy()
        {
            button.onClick.RemoveListener(OnClick);
            guideButton.onClick.RemoveListener(OnClickGuild);
        }

        public static Instruction instance
        {
            get
            {
                if (_instance != null)
                {
                    GameObject canvas = GameObject.FindGameObjectWithTag("MainCanvas");
                    _instance.transform.SetParent(canvas.transform);
                    _instance.transform.localScale = Vector3.one;
                    _instance.transform.localPosition = Vector3.zero;
                    return _instance;
                }
                else
                {
                    GameObject resource = Resources.Load<GameObject>(Defines.PrefabResourceURL.InstructionPrefab);
                    GameObject gameObject = Instantiate<GameObject>(resource, GameObject.FindGameObjectWithTag("MainCanvas").transform);
                    gameObject.transform.localPosition = Vector3.zero;
                    _instance = gameObject.GetComponent<Instruction>();
                gameObject.SetActive(false);
                    return _instance;
                }

            }
        }

        public void Show(string message = "", string instructionDynamicResource = "", float delayTime = 0f, bool blur = true)
        {
            blurBackground.SetActive(blur);
            gameObject.SetActive(true);
            localizingIconObject.SetActive(false);
            successIconObject.SetActive(false);
            button.gameObject.SetActive(false);
            guideButton.gameObject.SetActive(false);

            if (string.IsNullOrEmpty(message)) controlText.gameObject.SetActive(false);
            else controlText.gameObject.SetActive(true);
            controlText.text = message;

            foreach (Transform oldContent in dynamicUI.transform)
            {
                oldContent.gameObject.SetActive(false);
            }

            if (!string.IsNullOrEmpty(instructionDynamicResource))
            {
                if (dynamicContent.ContainsKey(instructionDynamicResource))
                {
                    dynamicContent[instructionDynamicResource].SetActive(true);
                }
                else
                {
                    GameObject dynamicPrefab = Instantiate(Resources.Load<GameObject>(instructionDynamicResource));
                    dynamicPrefab.transform.SetParent(dynamicUI.transform);
                    dynamicPrefab.GetComponent<RectTransform>().localScale = Vector3.one;
                    dynamicContent.Add(instructionDynamicResource, dynamicPrefab);
                }
            }
            UpdateLayout();

            if (delayTime > 0f)
            {
                Invoke(nameof(Hide), delayTime);
            }
        }

        public void ExitFirstScanning()
        {
            EventManager.Instance.PostNotification(EVENT_TYPE.Back, this, null);
            API.BackToHomeScreen("");

        }

        public void ShowButton(Action callback, string buttonText = "")
        {
            button.gameObject.SetActive(true);
            TextMeshProUGUI textGUI = button.GetComponentInChildren<TextMeshProUGUI>();
            textGUI.text = buttonText;
            if (callback != null)
            {
                this.callback = callback;
            }
            UpdateLayout();
        }

        public void ShowGuideButton(string prefabResourceURL, string buttonText = "", Action callBack = null)
        {
            guideButton.gameObject.SetActive(true);
            TextMeshProUGUI textGUI = guideButton.GetComponentInChildren<TextMeshProUGUI>();
            textGUI.text = buttonText;
            guidePrefabResourceURL = prefabResourceURL;
            UpdateLayout();
            if (callback != null)
                hideAction = callback;
        }

        private void UpdateLayout()
        {
            foreach (var layout in GetComponentsInChildren<LayoutGroup>())
            {
                LayoutRebuilder.ForceRebuildLayoutImmediate(layout.GetComponent<RectTransform>());
            }
        }

        private void OnClick()
        {
            Hide();
            if (callback != null)
            {
                callback.Invoke();
            }
        }

        private void OnClickGuild()
        {
            if (!string.IsNullOrEmpty(guidePrefabResourceURL))
            {
                instructionUI = InstructionUI.ScanningGuide;
                GameObject resource = Resources.Load<GameObject>(guidePrefabResourceURL);
                guideGameObject = Instantiate<GameObject>(resource, GameObject.FindGameObjectWithTag("MainCanvas").transform);
                if (guideGameObject.GetComponent<UIPanelsSliderController>())
                    guideGameObject.GetComponent<UIPanelsSliderController>().onSliderDestroy += HandleWhenDestroySlider;
            }
        }

        public void Hide()
        {
            ExitWhileScanningButton.SetActive(false);
            gameObject.SetActive(false);
            Debug.Log("hideAction" + hideAction);
            hideAction?.Invoke();
            hideAction = null;
            if (guideGameObject)
            {
                Instruction.instance.instructionUI = Instruction.InstructionUI.LocalizingInstruction;
                Destroy(guideGameObject);
            }
        }

        public void ChangeBlockScanStatus(string message = "", SubNotify typeOfSubNotify = SubNotify.Localizing, float delayTime = 0f)
        {
            successIconObject.transform.parent.gameObject.SetActive(true);
            controlText.text = message;
            if (!string.IsNullOrEmpty(message)) controlText.gameObject.SetActive(true);
            else controlText.gameObject.SetActive(false);
            switch (typeOfSubNotify)
            {
                case SubNotify.Localizing:
                    localizingIconObject.SetActive(true);
                    successIconObject.SetActive(false);
                    break;
                case SubNotify.Success:
                    localizingIconObject.SetActive(false);
                    successIconObject.SetActive(true);
                    break;
                default:
                    localizingIconObject.SetActive(false);
                    successIconObject.SetActive(false);
                    break;
            }
            UpdateLayout();

            if (delayTime > 0f)
            {
                Invoke(nameof(Hide), delayTime);
            }
        }

        public InstructionUI GetInstructionUIType()
        {
            return instructionUI;
        }

        private void HandleWhenDestroySlider()
        {
            Debug.Log("Destroy scaning guide");
            Instruction.instance.instructionUI = Instruction.InstructionUI.LocalizingInstruction;
        }
    }
}
