﻿using System;
using JLGames.RocketDriver.Actions.Utils;
using JLGames.RocketDriver.CSharp.DateTimex;
using UnityEngine;

namespace JLGames.RocketDriver.Games.PanelManager
{
    internal sealed class PanelInstance : IPanelInstance, IInternalPanelInstance
    {
        private static long m_InitValue;

        static PanelInstance()
        {
            m_InitValue = DateTimeUtil.NowHours1970;
        }

        //---------------------------------

        private readonly string m_InstanceId;
        private IPanelInfo m_Info;
        private GameObject m_DisplayView;
        private GameObject m_DisplayBackground;
        private GameObject m_DisplayContainer;

        private MonoBehaviour m_MainScript;
        public string InstanceId => m_InstanceId;
        public string PanelId => m_Info?.Id;
        public IPanelInfo Info => m_Info;
        public GameObject DisplayView => m_DisplayView;
        public GameObject DisplayBackground => m_DisplayBackground;
        public GameObject DisplayContainer => m_DisplayContainer;
        public bool IsCustomInitPanel => CastMainScript<IInitPanel>() != null;
        public bool IsCustomParamsPanel => CastMainScript<IParamsPanel>() != null;
        public bool IsCustomRefrshPanel => CastMainScript<IRefreshPanel>() != null;
        public bool IsCustomDisposePanel => CastMainScript<IDisposePanel>() != null;
        public MonoBehaviour MainScript => m_MainScript;

        public T CastMainScript<T>() where T : class
        {
            return MainScript as T;
        }

        public MonoBehaviour FindMainScript()
        {
            if (null == m_DisplayView || null == m_Info || !m_Info.AssetSettings.IncludeMainScript)
            {
                m_MainScript = null;
                return null;
            }

            m_MainScript = m_DisplayView.GetComponent(m_Info.AssetSettings.MainScriptName) as MonoBehaviour;
            return m_MainScript;
        }

        //---------------------------------

        public void Dispose()
        {
            m_MainScript = null;
            m_DisplayView = null;
            m_DisplayContainer = null;
        }

        //---------------------------------

        public PanelInstance(string panelId)
        {
            m_InstanceId = GenInstanceId();
            var info = PanelManagerShared.Manager.Register.GetPanelInfo(panelId);
            SetPanelInfo(info);
        }

        public PanelInstance(IPanelInfo panelInfo)
        {
            m_InstanceId = GenInstanceId();
            SetPanelInfo(panelInfo);
        }

        public void SetPanelInfo(IPanelInfo info)
        {
            if (null == info)
            {
                throw new NullReferenceException();
            }

            m_Info = info;
            InitContainer();
            InitBackground();
        }

        public void SetDisplayView(GameObject view)
        {
//            DebugUtil.Log("SetDisplay:", display);
            if (null == view) return;

            m_DisplayView = view;
            FindMainScript();
        }

        public void InvokeBackgroundAction(bool onEndOfFrame)
        {
            if (null == m_DisplayBackground || null == m_DisplayContainer || null == m_Info) return;
            var settings = m_Info.Settings.BackgroundSettings;
            var script = ComponentUtil.GetComponentByName(m_DisplayBackground, settings.OriginInfo?.Script);
            if (null == script) return;

            switch (settings.Mode)
            {
                case PanelBackgroundMode.Color:
                    (script as IBgColor)?.SetColor(settings, onEndOfFrame);
                    break;
                case PanelBackgroundMode.Image:
                    (script as IBgImage)?.SetImage(settings, onEndOfFrame);
                    break;
                case PanelBackgroundMode.Screenshot:
                    (script as IBgScreenshot)?.SetScreenshot(settings, onEndOfFrame);
                    break;
            }
        }

        public void AppendViewToContainer()
        {
            TransformUtil.AddChildTo(m_DisplayView.transform, m_DisplayContainer.transform);
        }

        private void InitContainer()
        {
            var contaienr = PanelManagerShared.Manager.Register.PanelContainerOrigin;
            if (null != contaienr)
            {
                var rs = UnityEngine.Object.Instantiate(contaienr);
                if (!rs.activeSelf) rs.SetActive(true);
                m_DisplayContainer = rs;
            }
            else
            {
                m_DisplayContainer = new GameObject();
            }

            m_DisplayContainer.name = $"Panel_{InstanceId}";
        }

        private void InitBackground()
        {
            var settings = m_Info.Settings.BackgroundSettings;
            var bgMode = settings.Mode;
            if (bgMode == PanelBackgroundMode.None || settings.OriginInfo == null || settings.OriginInfo.Origin == null) return;

            var bg = UnityEngine.Object.Instantiate(settings.OriginInfo.Origin);
            TransformUtil.AddChildTo(bg.transform, DisplayContainer.transform);
            m_DisplayBackground = bg;
        }

        private string GenInstanceId()
        {
            m_InitValue += 1;
            return $"{m_InitValue:X}";
        }
    }
}