using FL.Nodes.GameMain;
using System;
using UnityEngine;
using XGame.Database;
using XGame.Framework.Components;
using XGame.Framework.Map;
using XGame.Framework.Time;

namespace FL.Battle
{
    public interface ISkillContext
    {
        IEntity Entity { get; }
        Vector3 Position { get; }
        ITimeModule Time { get; }
        void FindTarget(int skillId);
        void EnqueueSkill(int skillId);
    }
    public class SkillComponent : Component<ISkillContext>
    {
        public override int Order => 0;

        private IEntityView _targetView;
        private IEntity _target;
        private IAlarm _cdAlarm;
        private ITimer _skillTimer;
        private long _lastAtkTime;
        public bool IsPlaying { get; private set; }

        public void SetTarget(IEntityView targetView, IEntity target)
        {
            _targetView = targetView;
            _target = target;
        }
        public void Start(int skillId, Action onCompleted)
        {
            var skill = SkillTableRepo.Get(skillId);
            var owner = Context.Entity;
            //if (_target == null)
            //{
            //    Log.Error($"OnStartAttack Error: Target is null. TableId:{Context.Owner.TableId} State:{Context.Owner.State}");
            //    return;
            //}
            if (_target == null || _target.State == EEntityState.Dead)
            {
                Stop();
                onCompleted?.Invoke();
                Context.FindTarget(skillId);
                return;
            }
            if (owner.State == EEntityState.Dead)
            {
                Stop();
                onCompleted?.Invoke();
                return;
            }
            IsPlaying = true;
            var hpValue = _targetView.GetComponent<HpComponent>().CalculateHit(-10);
            var dto = new SkillEffectDto()
            {
                skillEffect = skill.SkillEffect,
                hitEffect = skill.HitEffect,
                bulletEffect = skill.BulletEffect,
                skillTime = skill.EndureTime,
                from = Context.Position,
                to = _targetView.Position,
                hpAdd = new HpAddDto()
                {
                    position = _targetView.Position,
                    hpValue = hpValue,
                }
            };
            EventSingle.Instance.Notify(EventDefine.GameMainMapSkillEffect, dto);
            if (dto.skillTime > 0)
            {
                _skillTimer = Context.Time.AddDelayTimer(dto.skillTime, () =>
                {
                    OnAttackEnd(skillId);
                    onCompleted?.Invoke();
                });
            }
            else
            {
                OnAttackEnd(skillId);
                onCompleted?.Invoke();
            }
        }
        public void Stop()
        {
            _cdAlarm?.Cancel();
            _cdAlarm = null;
            _skillTimer?.Cancel();
            _skillTimer = null;
            _targetView = null;
            _target = null;
            IsPlaying = false;
        }
        protected override void OnDispose()
        {
            Stop();
        }
        private void OnAttackEnd(int skillId)
        {
            IsPlaying = false;
            _lastAtkTime = Context.Time.GetNowTime();
            //ÀäÈ´¼ÆÊ±
            var time = _lastAtkTime + SkillTableRepo.Get(skillId).RestTime;
            _cdAlarm = Context.Time.AddAlarm(() =>
            {
                Context.EnqueueSkill(skillId);
            }, time);
        }
    }
}
