using System;
using System.Collections.Generic;
using Fort23.Core;
using Fort23.UTool;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Fort23.Mono
{
    /// <summary>
    /// 打开一个UI的流程是：
    /// 1.生成Entity脚本
    /// 2.通过Init方法获取到数据
    /// 3.如果数据获取失败了，则界面打开失败，直接调用Entity的Dispose方法销毁；如果数据获取成功则调用Show展示界面。
    /// </summary>
    public class UIBase : Entity
    {
        private RectTransform _transform;

        public RectTransform transform => _transform;

        public GameObject GObjectPoolInterface;

        /// <summary>
        /// 序列化数据，用于拖动使用
        /// </summary>
        protected ReferenceCollector _referenceCollector;

        protected bool _isShow;

        /// <summary>
        /// 标记是否打开状态
        /// </summary>
        public bool isShow
        {
            get { return _isShow; }
            set { _isShow = value; }
        }

        /// <summary>
        /// 是否添加了button事件
        /// </summary>
        private bool _isAddButtonEvent;

        /// <summary>
        /// 是否启用动画
        /// </summary>
        public bool isActiveAnima;

        public Animator Animator;


        /// <summary>
        /// 结束动画的长度
        /// </summary>
        protected long _closeAnimationTimeCount;

        /// <summary>
        /// 开始动画的长度
        /// </summary>
        protected long _openAnimationTimeCount;

        /// <summary>
        /// 是否展示完成
        /// </summary>
        public bool IsShowComplete = true;

        public CTask hideCtask;
        
        
        protected CTask showcCTask;

        /// <summary>
        /// 这个方法可以用来替代Awake，直接重写就可以不注册Awake系统了。
        /// </summary>
        /// <param name="gObjectPoolInterface"></param>
        public virtual async CTask SetUIGameObject(GameObject gObjectPoolInterface)
        {
            GObjectPoolInterface = gObjectPoolInterface;
            _transform = gObjectPoolInterface.GetComponent<RectTransform>();
            _transform.anchoredPosition = Vector2.zero;
            _referenceCollector = gObjectPoolInterface.GetComponent<ReferenceCollector>();


            Animator = gObjectPoolInterface.GetComponent<Animator>();

            // this.isActiveAnima = isActiveAnima;

            if (!_isAddButtonEvent)
            {
                AddButtonEvent();
                _isAddButtonEvent = true;
            }


            if (Animator != null && Animator.runtimeAnimatorController != null )
            {
                Animator.updateMode = AnimatorUpdateMode.UnscaledTime;
                foreach (var animatorClip in Animator.runtimeAnimatorController.animationClips)
                {
                    if (animatorClip.name.Contains("close") || animatorClip.name.Contains("Close"))
                    {
                        _closeAnimationTimeCount = (long)(animatorClip.length * 1000);
                    }

                    if (animatorClip.name.Contains("open") ||  animatorClip.name.Contains("Open"))
                    {
                        _openAnimationTimeCount = (long)(animatorClip.length * 1000);
                    }
                }
            }
        }

        /// <summary>
        /// UI一次打开的时候调用一次，后面就不会再调用
        /// </summary>
        public virtual void AddButtonEvent()
        {
        }

        public override bool IsUpdate()
        {
            if (GObjectPoolInterface == null)
            {
                return false;
            }

            return GObjectPoolInterface.activeInHierarchy;
        }

        /// <summary>
        /// 获取UI拖动的部件信息
        /// </summary>
        /// <param name="key"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetUIUnit<T>(string key) where T : class
        {
            return _referenceCollector.Get<T>(key);
        }

        /// <summary>
        /// 初始化相关数据(针对内部请求初始化) 可使用异步等待 与自动化Init 区分开
        /// 先初始化数据，然后再打开界面，可以避免某些界面先打开后才被初始化
        /// </summary>
        /// <returns></returns>
        public virtual async CTask<bool> AsyncInit(object[] uiData)
        {
            try
            {
                CTask<bool> cTask = CTask<bool>.Create();
                cTask.SetResult(true);
                return await cTask;
            }
            catch (Exception e)
            {
                LogTool.Exception(e);
            }

            return default;
        }


        /// <summary>
        /// 打开界面
        /// </summary>
        public virtual async CTask Open()
        {
            await Show();
        }

        public virtual  CTask Show()
        {
            if (GObjectPoolInterface == null)
            {
                return null;
            }

            CTask cTask = CTask.Create();
            _isShow = true;
            GObjectPoolInterface.SetActive(true);
            if (timerEntity != null)
            {
                TimerComponent.Instance.Remove(timerEntity);
            }

            if (openTimerEntity != null)
            {
                TimerComponent.Instance.Remove(openTimerEntity);
            }


            ShowAnimator();
            cTask.SetResult();

            return cTask;
        }

        public virtual void ShowAnimator()
        {
            showcCTask = CTask.Create(false);
            TimerComponent.Instance.Remove(openTimerEntity);
            if (Animator != null && isActiveAnima)
            {
                if (_openAnimationTimeCount > 0)
                {
                    Animator.Play("open", 0, 0.01f);
                    Animator.Update(0.01f);
                    openTimerEntity = TimerComponent.Instance.AddTimer(_openAnimationTimeCount, delegate
                    {
                        showcCTask.SetResult();
                    });
                }
                else
                {
                    showcCTask.SetResult();
                }
            }
            else
            {
                showcCTask.SetResult();
            }
        }

        protected TimerEntity timerEntity;
        protected TimerEntity openTimerEntity;



        //等大show动画播放完毕
        public async CTask WaitShowAnimOver()
        {
            await showcCTask;
        }
        
        /// <summary>
        /// 隐藏界面
        /// </summary>
        public virtual async void Hide()
        {
            hideCtask = CTask.Create(false);
            _isShow = false;

            if (Animator != null && isActiveAnima)
            {
                Animator.Play("close");

                if (timerEntity != null)
                {
                    TimerComponent.Instance.Remove(timerEntity);
                }

                timerEntity = TimerComponent.Instance.AddTimer(_closeAnimationTimeCount,
                    () =>
                    {
                        if (GObjectPoolInterface != null)
                        {
                            GObjectPoolInterface.SetActive(false);
                        }

                     
                        hideCtask.SetResult();
                    });
            }
            else
            {
                if (GObjectPoolInterface != null)
                {
                    GObjectPoolInterface.SetActive(false);
                }
                hideCtask.SetResult();
            }
        }

        public async CTask PlayAnim(string anmiName)
        {
            CTask cTask = CTask.Create();
            long animaTimeCount = 0;
            if (Animator != null && Animator.runtimeAnimatorController != null && isActiveAnima == true)
            {
                Animator.updateMode = AnimatorUpdateMode.UnscaledTime;
                foreach (var animatorClip in Animator.runtimeAnimatorController.animationClips)
                {
                    if (animatorClip.name.Contains(anmiName))
                    {
                        animaTimeCount = (long)(animatorClip.length * 1000);
                    }
                }
            }

            Animator.Play(anmiName);
            TimerComponent.Instance.AddTimer(animaTimeCount,
                () => { cTask?.SetResult(); });

            await cTask;
        }


        public override async void Dispose()
        {
            if (GObjectPoolInterface != null)
            {
                OnDestroy();
                GameObject.Destroy(GObjectPoolInterface);
                GObjectPoolInterface = null;
            }

            base.Dispose();
        }

        protected virtual void OnDestroy()
        {
        }
    }
}