using FairyGUI;
using FL.Battle;
using FL.Map.UI;
using FL.Nodes.GameMain;
using System.Collections.Generic;
using UnityEngine;
using XGame;
using XGame.Database;
using XGame.Framework.Asyncs;
using XGame.Framework.Components;
using XGame.Framework.Interfaces;
using XGame.Framework.Map;
using XGame.Framework.Time;

namespace FL.Map.TestMainMap
{
    public interface IMapUIContext
    {
        IMapAssetModule Asset { get; }
        ITimeModule Time { get; }
        TestMainMapVM VM { get; }
    }
    /// <summary>
    /// 地图用UI
    /// </summary>
    public class MapUIComponent : Component<IMapUIContext>, ILateUpdate
    {
        private MainMapUIView _uiView;
        private IAsync _uiViewAsync;
        /// <summary>
        /// 玩家、怪物血条
        /// </summary>
        private Dictionary<long, EntityBattleInfoView> _entityViewsMap = new Dictionary<long, EntityBattleInfoView>();
        /// <summary>
        /// 飘血计时
        /// 同一个Entity的飘血需要有200毫秒间隔
        /// </summary>
        private Dictionary<long, long> _hpAddLastTimeMap = new Dictionary<long, long>();
        /// <summary>
        /// TODO
        /// </summary>
        private Camera UICamera => StageCamera.main;
        protected override void OnEnable(object intent)
        {
            EventSingle.Instance.AddListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
            EventSingle.Instance.AddListener(EventDefine.GameMainMapHpAdd, OnHpAdd);
            LoadUIView();
        }

        protected override void OnDisable()
        {
            EventSingle.Instance.RemoveListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
            EventSingle.Instance.RemoveListener(EventDefine.GameMainMapHpAdd, OnHpAdd);
            if (_uiView != null)
            {
                Context.Asset.Recycle(_uiView);
                _uiView = null;
            }
            if (_uiViewAsync != null)
            {
                _uiViewAsync.RemoveAll();
                _uiViewAsync = null;
            }
            foreach (var item in _entityViewsMap)
            {
                Context.Asset.Recycle(item.Value);
            }
            _entityViewsMap.Clear();
            _hpAddLastTimeMap.Clear();
        }
        protected override void OnDispose()
        {
        }
        void ILateUpdate.LateUpdate(int millisecond)
        {
            if (_entityViewsMap.Count == 0)
                return;
            var cameraMoving = Context.VM.Camera.IsMoving;
            foreach (var view in _entityViewsMap.Values)
            {
                if (cameraMoving || view.Master.IsMoving)
                {
                    view.LocalPosition = WorldToLocal(view.Master.UIPoint.position, _uiView.PlayerRoot);
                }
                view.RefreshBuffs();
            }
        }
        /// <summary>
        /// 世界坐标转指定UI节点的相对坐标
        /// </summary>
        /// <param name="position"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        private Vector2 WorldToLocal(Vector3 position, Transform parent)
        {
            var screenPoint = Context.VM.Camera.WorldToScreenPoint(position);
            RectTransformUtility.ScreenPointToLocalPointInRectangle(parent as RectTransform, screenPoint, UICamera, out var localPoint);
            return localPoint;
        }
        public void AddEntity(ITarget master)
        {
            if (_uiView == null)
            {
                if (_uiViewAsync != null)
                {
                    _uiViewAsync.On(_ =>
                    {
                        LoadEntityView(master);
                    });
                }
                else
                {
                    Log.Error($"MainMapUI不能为空.");
                }
            }
            else
            {
                LoadEntityView(master);
            }
        }
        public void RefreshEntity(long entityId)
        {
            if (_entityViewsMap.TryGetValue(entityId, out var view))
            {
                view.RefreshHp();
            }
        }
        private void LoadEntityView(ITarget master)
        {
            GetEntityAddressable(master, out var addressable, out var parent);
            var viewAsync = Context.Asset.LoadEntity<EntityBattleInfoView>(addressable, parent);
            viewAsync.On(_ =>
            {
                var view = viewAsync.Result;
                if (view == null)
                    return;
                if (master.IsDead)
                {
                    Log.Debug($"EntityBattleInfoView 加载完成，Entity已经死亡. Id:{master.Entity.EntityId}");
                    Context.Asset.Recycle(view);
                    return;
                }
                view.Master = master;
                view.LocalPosition = WorldToLocal(master.UIPoint.position, _uiView.PlayerRoot);
                _entityViewsMap.Add(view.Master.Entity.EntityId, view);
            });
        }
        private void GetEntityAddressable(ITarget master, out string addressableName, out Transform parent)
        {
            if (master.Entity.EntityType == EEntityType.Monster)
            {
                var table = MonsterTableRepo.Get(master.Entity.TableId);
                if (table.Type == 2)
                {
                    addressableName = AddressableDefine.bossbattleinfo;
                }
                else
                {
                    addressableName = AddressableDefine.monsterbattleinfo;
                }
                parent = _uiView.MonsterRoot;
            }
            else
            {
                addressableName = AddressableDefine.playerbattleinfo;
                parent = _uiView.PlayerRoot;
            }
        }
        private void OnRemoveEntity(int eventId, object args)
        {
            var entityId = (long)args;
            if (_entityViewsMap.TryGetValue(entityId, out var view))
            {
                _entityViewsMap.Remove(entityId);
                Context.Asset.Recycle(view);
            }
            _hpAddLastTimeMap.Remove(entityId);
        }
        private void OnHpAdd(int eventId, object args)
        {
            PlayHpAdd((HpAddDto)args);
        }
        private void PlayHpAdd(HpAddDto dto)
        {
            if (_uiView == null)
                return;
            RefreshEntity(dto.entityId);
            SaveHpAddTime(dto.entityId, out var delay);
            if (delay > 0)
            {
                var timer = Context.Time.AddDelayTimer(delay, () =>
                {
                    LoadHpAddView(dto);
                });
            }
            else
            {
                LoadHpAddView(dto);
            }

        }
        private void LoadHpAddView(HpAddDto dto)
        {
            var viewAsync = Context.Asset.LoadEntity<HpAddEntityView>(AddressableDefine.uihpadd, _uiView.CombatValRoot);
            viewAsync.On(_ =>
            {
                var hpAddView = viewAsync.Result;
                if (hpAddView == null)
                    return;
                var localPoint = WorldToLocal(dto.position, _uiView.CombatValRoot);
                //var screenPoint = Context.VM.Camera.WorldToScreenPoint(dto.position);
                //RectTransformUtility.ScreenPointToLocalPointInRectangle(_uiView.CombatValRoot as RectTransform, screenPoint, UICamera, out var localPoint);
                hpAddView?.ShowValue(dto.hpValue, localPoint, dto.elementType, () =>
                {
                    Context.Asset.Recycle(hpAddView);
                });
            });
        }
        /// <summary>
        /// 保存时间
        /// </summary>
        /// <param name="entityId"></param>
        /// <param name="delay">延迟播放时间，单位:毫秒</param>
        private void SaveHpAddTime(long entityId, out int delay)
        {
            delay = 0;
            var curTime = Context.Time.GetNowTime();
            if (_hpAddLastTimeMap.TryGetValue(entityId, out var lastTime))
            {
                const int interval = 200;
                var playTime = lastTime + interval;
                if (playTime > curTime)
                {
                    lastTime = playTime;
                    delay = (int)(playTime - curTime);
                }
                else
                {
                    lastTime = curTime;
                }
            }
            else
            {
                lastTime = curTime;
            }
            _hpAddLastTimeMap[entityId] = lastTime;
        }
        private void LoadUIView()
        {
            var loadAsync = Context.Asset.LoadEntity<MainMapUIView>(AddressableDefine.mainmapui, Context.VM.UIRoot);
            _uiViewAsync = loadAsync;
            loadAsync.On(_ =>
            {
                _uiViewAsync = null;
                var uiView = loadAsync.Result;
                if (uiView == null)
                    return;
                _uiView = uiView;
            });
        }


    }
}
