using DG.Tweening;
using FL.Battle.Actions;
using FL.Battle.Components;
using System;
using UnityEngine;
using XGame.Database;
using XGame.Framework;
using XGame.Framework.Interfaces;

namespace FL.Battle.Skills
{
    /// <summary>
    /// 普通攻击
    /// </summary>
    internal class AttackActor : ISkillActor
    {
        public ISkillContext Context { get; set; }
        void ISkillActor.Play(int skillId, ITarget target, Action<int, int> onCompleted)
        {
            var owner = Context.Entity;

            if (Context.Entity.EntityType != EEntityType.Partner)
            { // 玩家或者怪物
                PlaySkillAtk(target, onCompleted);
                //Context.Spine.Play(ActionName.attack, () =>
                //{
                //    OnHitFrame();
                //    OnAttackEnd();
                //    Context.Spine.Play(ActionName.idle);
                //    onCompleted?.Invoke();
                //});
                return;
            }
            // 随从
            PartnerType partnerType = (PartnerType)((Context.Entity.TableId / 100) % 10);
            //单手剑、双手剑、法杖使用法术类型攻击
            var isSkill = partnerType == PartnerType.Sword || partnerType == PartnerType.Wand;
            if (isSkill)
            {
                PlaySkillAtk(target, onCompleted);
            }
            else
            {
                PartnerNormalAtk(target, onCompleted);
            }
        }

        private void PlaySkillAtk(ITarget target, Action<int, int> onCompleted)
        {
            var actArgs = new AnimationPlayArgs()
            {
                aniName = EAnimationName.attack,
                onCompleted = () =>
                {
                    //Context.Animator.Play(EAnimationName.idle/* + UnityEngine.Random.Range(0, 100) % 2*/);
                    if (target == null || target.IsDead)
                    {
                        //OnAttackEnd();
                        onCompleted.SafeInvoke(0, Context.Entity.Attr.AttackCD);
                        return;
                    }
                    var to = target.Position;

                    var actMove = ObjectPool.Acquire<MoveBezierAction>();
                    actMove.args.from = Context.Position;
                    actMove.args.to = to;
                    actMove.args.duration = 500;
                    var bulletArgs = ObjectPool.Acquire<VfxArgs>();
                    bulletArgs.vfxName = Context.Entity.EntityType == EEntityType.Partner ? "effect_atk_bullet_20181" : "atk_007";
                    bulletArgs.duration = 500;
                    bulletArgs.followType = EVfxFollowType.World;
                    bulletArgs.action = actMove;
                    bulletArgs.onFinish = () =>
                    {
                        OnHitFrame(target);
                    };

                    var actPosition = ObjectPool.Acquire<PositionAction>();
                    actPosition.position = to;
                    var hitArgs = ObjectPool.Acquire<VfxArgs>();
                    hitArgs.vfxName = Context.Entity.EntityType == EEntityType.Partner ? "effect_atk_hit_20181" : "hit_007";
                    hitArgs.duration = 2000;
                    hitArgs.followType = EVfxFollowType.World;
                    hitArgs.action = actPosition;
                    bulletArgs.next = hitArgs;
                    Context.Vfx.Play(bulletArgs);
                    //var dto = new SkillEffectDto()
                    //{
                    //    skillEffect = "",
                    //    skillTime = 667,
                    //    from = Context.Position,
                    //    to = _targetView.Position,
                    //    hpAdd = new HpAddDto()
                    //    {
                    //        position = _targetView.Position,
                    //        hpValue = hpValue,
                    //    }
                    //};
                    //if (Context.Entity.EntityType == EEntityType.Partner)
                    //{
                    //    dto.hitEffect = "effect_atk_hit_20181";
                    //    dto.bulletEffect = "effect_atk_bullet_20181";
                    //}
                    //else
                    //{
                    //    dto.hitEffect = "hit_007";
                    //    dto.bulletEffect = "atk_007";
                    //}
                    //EventSingle.Instance.Notify(EventDefine.GameMainMapSkillEffect, dto);

                    //OnAttackEnd();
                    onCompleted.SafeInvoke(0, Context.Entity.Attr.AttackCD);
                }
            };
            Context.Animator.Play(actArgs);
        }
        private void PartnerNormalAtk(ITarget target, Action<int, int> onCompleted)
        {
            var from = Context.Position;
            var to = target.Position;
            var distance = Vector3.Distance(from, to);
            var atkRange = 0;// _target.Attr.Radius;
            if (distance > atkRange)
            { // 大于攻击距离
                //Log.Info($"PlayAttack:Owner:{Handle.Owner.EntityId} Target:{_target.EntityId}");
                var dir = (to - from).normalized;
                var moveDis = distance - atkRange;
                var atkPosition = Context.ActionRoot.localPosition + dir * moveDis;
                //var moveTime = 0.42f;// Mathf.Abs(moveDis) / 5;
                Context.ActionRoot.localPosition = atkPosition;
                var actArgs = new AnimationPlayArgs()
                {
                    aniName = EAnimationName.attack,
                    onCompleted = () =>
                    {
                        //Context.Animator.Play(EAnimationName.idle/* + UnityEngine.Random.Range(0, 100) % 2*/);
                        Context.ActionRoot.localPosition = Vector3.zero;
                        var endArgs = ObjectPool.Acquire<VfxArgs>();
                        endArgs.vfxName = "effect_melee_appear";
                        endArgs.duration = 500;
                        Context.Vfx.Play(endArgs);

                        OnHitFrame(target);
                        //OnAttackEnd();
                        onCompleted.SafeInvoke(0, Context.Entity.Attr.AttackCD);
                    }
                };
                Context.Animator.Play(actArgs);
                var startArgs = ObjectPool.Acquire<VfxArgs>();
                startArgs.vfxName = "effect_melee_blink";
                startArgs.duration = 500;
                Context.Vfx.Play(startArgs);
                //MoveTo(atkPosition, moveTime, () =>
                //{
                //    OnHitFrame();
                //    //moveback
                //    MoveTo(Vector3.zero, moveTime, () =>
                //    {
                //        OnAttackEnd();
                //        onCompleted?.Invoke();
                //    });

                //});
            }
            else
            {
                OnHitFrame(target);
                //OnAttackEnd();
                onCompleted.SafeInvoke(0, Context.Entity.Attr.AttackCD);
            }
        }
        public void Stop()
        {
            Context.ActionRoot.DOKill();
            Context.ActionRoot.localPosition = Vector3.zero;
        }
        private void MoveTo(Vector3 to, float duration, Action callback)
        {
            var tween = Context.ActionRoot.DOLocalMove(to, duration);
            tween.onComplete = () =>
            {
                callback.SafeInvoke();
            };
        }
        private void OnHitFrame(ITarget target)
        { // 攻击帧回调
            //TODO 目标受击
            if (target == null || target.IsDead)
                return;
            target.Calculation.Damage(-Context.Entity.Attr.Attack, EElementType.None);
        }

        void IReference.Clear()
        {
            Stop();
            Context = null;
        }
        //private void OnAttackEnd()
        //{
        //    _lastAtkTime = Context.Time.GetNowTime();
        //    //冷却计时
        //    var time = _lastAtkTime + Context.Entity.Attr.AttackCD;
        //    _cdAlarm = Context.Time.AddAlarm(() =>
        //    {
        //        Context.EnqueueSkill(0);
        //    }, time);
        //}
    }
}
