using FL.Battle;
using System.Collections.Generic;
using UnityEngine;
using XGame.Framework.Map;
using XGame.Framework.Time;

namespace FL.Map
{
    public abstract class BattleEntityView<TViewModel> : EntityView<TViewModel>, IMoveContext, ITargetHandle, IHpContext where TViewModel : EntityViewModel
    {
        private IEntity _entity;
        public IEntity Entity
        {
            get => _entity;
            set
            {
                _entity = value;
                LocalPosition = value?.TargetPosition ?? Vector3.zero;
                State = EEntityState.Idle;
            }
        }
        #region 状态
        private ITimer _deadTimer;
        public EEntityState State
        {
            get => _entity.State;
            set
            {
                if (value != EEntityState.Idle && value == _entity.State)
                {
                    return;
                }
                if (_entity.State == EEntityState.Dead)
                { // 已经死亡，不能再修改状态
                    return;
                }
                _entity.State = value;
                //VM.StateText.text = value.ToString();
                //Animation
                if (value == EEntityState.Idle)
                    GetComponent<SpineComponent>().Play(ActionName.idle);
                else if (value == EEntityState.Dead)
                {
                    //TODO 死亡动作  停止所有组件
                    _deadTimer = Context.Time.AddDelayTimer(500, () =>
                    { // 死亡事件通知
                        _deadTimer = null;
                        EventSingle.Instance.Notify(EventDefine.GameMainMapRemoveEntity, _entity.EntityId);
                    });
                }
                OnStateChanged();
            }
        }
        public bool IsDead => _entity.State == EEntityState.Dead;
        #endregion

        #region IMoveContext
        public bool IsMoving => GetComponent<MoveComponent>().IsMoving;
        Transform IMoveContext.OwnerTr => VM.Tr;
        #endregion

        #region ITargetSelectContext
        //Vector3 ITargetSelectHandle.Position => Position;
        float ITargetHandle.Radius => _entity.Attr.Radius;
        float ITargetHandle.AtkRange => _entity.Attr.AtkRange;
        void ITargetHandle.SelectTarget(ITargetHandle target, int skillId)
        {
            var targetView = target as IEntityView;
            State = EEntityState.Battle;
            if (skillId > 0)
            {
                GetComponent<SkillComponent>().SetTarget(targetView, target.Entity);
                EnqueueSkill(skillId);
            }
            GetComponent<AttackComponent>().SetTarget(targetView, target.Entity);
            EnqueueSkill(0);
        }
        #endregion
        #region 技能
        private int _playingSkill = -1;
        /// <summary>
        /// 技能队列
        /// 冷却时间到的技能进入队列等待播放
        /// </summary>
        private Queue<int> _skillQueue = new Queue<int>();
        /// <summary>
        /// 冷却时间到的技能进入队列等待播放
        /// </summary>
        /// <param name="skillId"></param>
        public void EnqueueSkill(int skillId)
        {
            if (State == EEntityState.Dead) 
                return;
            _skillQueue.Enqueue(skillId);
            if (_playingSkill == -1)
            {
                StartSkill();
            }
        }
        private void StartSkill()
        {
            if (_skillQueue.Count == 0 || State == EEntityState.Dead)
                return;
            var skillId = _skillQueue.Dequeue();
            _playingSkill = skillId;
            if (skillId > 0)
            { // 技能
                GetComponent<SkillComponent>().Start(skillId, OnSkillCompleted);
            }
            else
            { //普通攻击
                GetComponent<AttackComponent>().Start(OnSkillCompleted);
            }
        }
        private void OnSkillCompleted()
        {
            _playingSkill = -1;
            StartSkill();
        }
        #endregion

        protected override void OnDisable()
        {
            InnerClear();
        }
        //protected override void OnDispose()
        //{
        //    InnerClear();
        //    _entity = null;
        //}
        protected abstract void OnStateChanged();
        private void InnerClear()
        {
            _deadTimer?.Cancel();
            _deadTimer = null;
            _skillQueue.Clear();
            _playingSkill = -1;
        }
    }
}
