using System;
using Games.Events;
using Module.Log;
using System.Collections.Generic;
using GCGame.Table;
using UnityEngine;
using UnityEngine.Events;

namespace Games.LogicObj
{
    // 近世界层UI,该层UI可以认为是每一帧都需要重新拼合
    public class WorldUIRoot : MonoBehaviour
    {
        // 暂时不构造从UiManager向下初始化的结构,不析构的管理器直接用Instance自己管理
        public static WorldUIRoot Instance { get; private set; }
        //public const float maxScale = 1f;
        //public const float minScale = 0.2f;
        //// 像素宽度到世界宽度转化数值
        //public float PixelToWorld { get; private set; }

        private List<WorldUIItem> _uiItemList;
        private UiItemPool<WorldUIItem, WorldUiLoadData, WorldUiLoadTask> _uiItemPool;
        // Destroy之后不回收任何物品
        private bool _isDestroyed;
        private Canvas _canvas;

        #region  Head UI
        public static bool ShowHeadUi
        {
            get { return PlayerPreferenceData.SystemNameBoard; }
        }

        private RectTransform _headUiRoot;
        private RectTransform _damageUiRoot;

        public void ShowOrHideHeadRoot(bool IsShow)
        {
            if (_headUiRoot)
                _headUiRoot.gameObject.SetActive(IsShow);
        }

        public void ResetShowHeadUi()
        {
            for (var i = 0; i < _uiItemList.Count; i++)
            {
                var headUi = _uiItemList[i] as Obj_HeadUI;
                if (headUi)
                    headUi.ResetShow();
            }
        }

        /// <summary>
        /// 请求一个HeadUi物体
        /// </summary>
        public void LoadHeadUi(ObjParent objParent)
        {
            var loadData = new WorldUiLoadData(objParent, _headUiRoot, OnHeadUiLoadTaskComplete);
            _uiItemPool.PullItem(loadData, objParent.HeadUiPath);
        }

        public void StopLoadHeadUi(ObjParent objParent)
        {
            // 无视这个警告 - 常规指针检测方式
#pragma warning disable 252,253
            _uiItemPool.RemoveLoadTask(a => a.data == objParent);
#pragma warning restore 252,253
        }

        private void OnHeadUiLoadTaskComplete(WorldUIItem worldUiItem, WorldUiLoadData loadData)
        {
            if (worldUiItem == null)
                return;
            // Obj在加载中被析构的稀有情况
            if (loadData.data == null)
                _uiItemPool.PushItem(worldUiItem.uiPathData, worldUiItem);
            else
            {
                var error = false;
                try
                {
                    ((ObjParent)loadData.data).BindHeadUi(worldUiItem);
                }
                catch (Exception e)
                {
                    LogModule.ErrorLog(e.ToString());
                    error = true;
                }
                if (error)
                    worldUiItem.BackToPool();
                else
                    _uiItemList.Add(worldUiItem);
            }
        }
        #endregion
        #region Damage Board

        /// <summary>
        /// 显示伤害信息
        /// </summary>
        /// <param name="nType">伤害类型</param>
        /// <param name="strValue">字符串</param>
        /// <param name="pos">世界位置</param>
        /// <param name="isProfessionSkill">是否职业技能</param>
        public void ShowDamageBoard(int nType, string strValue, Vector3 pos, bool isProfessionSkill = true)
        {
            if (!PlayerPreferenceData.SystemDamageBoardEnable)
                return;
            var data = DamageBoardManager.damageBoardManager.TryAddDamageBoard(nType);
            if (data != null)
            {
                bool hightLayer = (
                       (nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.PLAYER_EXP_UP)
                    || (nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.YINPIAO_UP)
                    || (nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.YINLING_UP)
                    || (nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.YUANBAO_UP)
                    || (nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.LINGYU_UP)
                    );
                RectTransform _damageExpUiRoot = (UIManager.Instance() != null ? UIManager.Instance().DamageHightRoot : null);
                RectTransform root = (hightLayer && _damageExpUiRoot != null ? _damageExpUiRoot : _damageUiRoot);
                var taskStarter = new WorldUiLoadData(new DamageBoardData(data, strValue, pos, isProfessionSkill), root, OnDamageBoardLoadTaskComplete);
                _uiItemPool.PullItem(taskStarter, DamageBoard.PathData);
            }
        }
        private void OnDamageBoardLoadTaskComplete(WorldUIItem damageUiItem, WorldUiLoadData loadData)
        {
            var data = (DamageBoardData) loadData.data;
            var damageBoard = (DamageBoard) damageUiItem;
            damageBoard.ActiveDamageBoard(data.data, data.strValue, data.worldPos, data.isProfessionSkill);
            _uiItemList.Add(damageBoard);
        }
        // 注:这个指令应该同所有角色析构是同一帧,因此可以析构HeadUi
        public void ClearDamageBoard()
        {
            if (!_isDestroyed)
            {
                for (var i = 0; i < _uiItemList.Count; i++)
                {
                    var uiItem = _uiItemList[i];
                    if (uiItem.itemType == WorldUiItemType.DamageBoard)
                        Recovery(uiItem.uiPathData, uiItem);
                }
                DamageBoardManager.damageBoardManager.ClearNumber();
            }
        }
        #endregion
        
        #region AnchoredText

        public void ShowCountdownOnCharacter(int objId, int countdown)
        {
            var textData = new AnchoredTextData(objId, Time.unscaledTime + (float)countdown);
            var taskStarter = new WorldUiLoadData(textData, _damageUiRoot, OnCountDownLoadTaskComplete);
            _uiItemPool.PullItem(taskStarter, AnchoredText.PathData);
        }
        
        private void OnCountDownLoadTaskComplete(WorldUIItem damageUiItem, WorldUiLoadData loadData)
        {
            var data = (AnchoredTextData) loadData.data;
            var anchoredText = (AnchoredText) damageUiItem;
            anchoredText.SetInitData(data);
            _uiItemList.Add(anchoredText);
        }
        #endregion

        private void Awake()
        {
            Instance = this;
            _canvas = GetComponent<Canvas>();
            _uiItemList = new List<WorldUIItem>();
            _uiItemPool = new UiItemPool<WorldUIItem, WorldUiLoadData, WorldUiLoadTask>((RectTransform)transform.Find("PoolRoot"));
            _headUiRoot = (RectTransform)transform.Find("NameBoardRoot");
            _damageUiRoot = (RectTransform) transform.Find("DamageBoardRoot");
        }

        private void Start()
        {
            EventDispatcher.Instance.Add(Events.EventId.PostMainCameraMove, PostMainCameraMove);
            EventDispatcher.Instance.Add(Events.EventId.UiCameraCopy, OnUiCameraCopy);
            // 等TableManager一帧
            // PixelToWorld = 1f; float.Parse(TableManager.GetSystemParamByID(6, 0).StringValue);
        }

        private void OnDestroy()
        {
            if (Instance == this)
                Instance = null;
            _isDestroyed = true;
            EventDispatcher.Instance.Remove(Events.EventId.PostMainCameraMove, PostMainCameraMove);
            EventDispatcher.Instance.Remove(Events.EventId.UiCameraCopy, OnUiCameraCopy);
        }

        private int _hideCamera;
        private void OnUiCameraCopy(object args)
        {
            var start = (bool)args;
            _hideCamera = _hideCamera.ReplaceFlag(0.ToFlag(), start);
            ResetHideCamera();
        }

        //private void OnSceneMovie(object args)
        //{
        //    var start = (bool)args;
        //    _hideCamera = _hideCamera.ReplaceFlag(1.ToFlag(), start);
        //    ResetHideCamera();
        //}

        private void ResetHideCamera()
        {
            _canvas.enabled = _hideCamera <= 0;
        }

        private void PostMainCameraMove(object args)
        {
            // 注:可能有设置位置时,要求被回收的情况
            for (var i = _uiItemList.Count - 1; i >= 0; i--)
            {
                // 加固,防止固化流程被其他模块破坏
                try
                {
                    var activeItem = _uiItemList[i];
                    if (activeItem.CheckPositionValid() && activeItem.CheckDuration())
                    {
                        // 屏蔽缩放功能直到修复
                        //if (activeItem.scaleByWorldPos)
                        //    uiPos = GetUiPositionAndScale(activeItem.worldPosition, activeItem.pixelWidth, out scale);
                        //else
                        //{
                            var uiPos = UIManager.Instance().WorldToUiPoint(activeItem.worldPosition);
                            const float scale = 1f;
                        //}
                        activeItem.SetPositionAndScale(uiPos, scale);
                    }
                    else
                    {
                        // 伤害面板回收需要清除使用计数
                        if (activeItem.itemType == WorldUiItemType.DamageBoard && DamageBoardManager.damageBoardManager != null)
                        {
                            var damageBoard = (DamageBoard) activeItem;
                            DamageBoardManager.damageBoardManager.RemoveDamageBoard(damageBoard.data.DamageBoardTypeID);
                        }
                        activeItem.BackToPool();
                    }
                }
                catch (System.Exception e)
                {
                    LogModule.ErrorLog(_uiItemList[i] == null
                        ? "World Ui Root 中发现为空的物体!"
                        : string.Format("{0}发生故障!", _uiItemList[i].transform.GetHierarchyName()));
                    LogModule.ErrorLog(e.ToString());
                }
            }
        }

        /// <summary>
        /// 世界坐标转到UI坐标体系下的位置和缩放
        /// </summary>
        /// <param name="worldPos">世界坐标位置</param>
        /// <param name="pixelWidth">组件预期像素宽度</param>
        /// <param name="scale">Ui空间的缩放数值</param>
        //public Vector3 GetUiPositionAndScale(Vector3 worldPos, float pixelWidth, out float scale)
        //{
        //    var sceneCamera = UIManager.Instance().GetWorldCamera();
        //    var worldWidth = pixelWidth * PixelToWorld;
        //    // 默认世界摄像机是投影摄像机
        //    // 实际是摄像机的forward,叉乘之后才是right
        //    var right = worldPos - sceneCamera.transform.position;
        //    right = Vector3.Cross(Vector3.up, right);
        //    if (right == Vector3.zero)
        //        right = sceneCamera.transform.right;
        //    right = right.normalized;
        //    var pos0 = worldPos - right * 0.5f * worldWidth;
        //    var pos1 = worldPos + right * 0.5f * worldWidth;
        //    // 像素位置
        //    pos0 = UIManager.Instance().WorldToUiPoint(pos0);
        //    pos1 = UIManager.Instance().WorldToUiPoint(pos1);
        //    scale = Mathf.Clamp((pos1.x - pos0.x) / pixelWidth, minScale, maxScale);
        //    return (pos0 + pos1) * 0.5f;
        //}
        
        public void SetShow(bool isShow)
        {
            _canvas.enabled = isShow;
        }

        public void Recovery(UIPathData pathData, WorldUIItem item)
        {
            if (!_isDestroyed)
            {
                _uiItemList.Remove(item);
                _uiItemPool.PushItem(pathData, item);
            }
        }

        public class WorldUiLoadData : BaseLoadData<WorldUIItem, WorldUiLoadData>
        {
            public object data;
            public WorldUiLoadData(object pData, Transform root, UnityAction<WorldUIItem, WorldUiLoadData> callback) : base(root, callback)
            {
                data = pData;
            }
        }

        public class WorldUiLoadTask : BaseLoadTask<WorldUIItem, WorldUiLoadData, WorldUiLoadTask>
        {
        }

        public class DamageBoardData
        {
            public Tab_DamageBoardType data;
            public string strValue;
            public Vector3 worldPos;
            public bool isProfessionSkill;

            public DamageBoardData(Tab_DamageBoardType data, string strValue, Vector3 worldPos, bool isProfessionSkill)
            {
                this.data = data;
                this.strValue = strValue;
                this.worldPos = worldPos;
                this.isProfessionSkill = isProfessionSkill;
            }
        }

        public class AnchoredTextData
        {
            public int objId;
            public float endTime;

            public AnchoredTextData(int objId, float endTime)
            {
                this.objId = objId;
                this.endTime = endTime;
            }
        }

        public enum WorldUiItemType
        {
            HeadInfo, // 头顶面板
            DamageBoard, // 伤害面板
            AnchorText, // 倒计时面板
        }
    }
}