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

namespace FL.Battle.Skills
{
    /// <summary>
    /// 简单的技能表现
    /// </summary>
    internal class SimpleSkillActor : ISkillActor, IReference
    {
        public ISkillContext Context { get; set; }

        private ITimer _skillTimer; //技能施法时间 
        private ITimer _bulletTimer;
        private ITimer _noAniTimer; // 没有动作时受击特效的定时器
        private SkillTable _skill;
        private SkillVfxsTable _skillVfxs;

        void ISkillActor.Play(int skillId, ITarget target, Action<int, int> onCompleted)
        {
            _skill = SkillTableRepo.Get(skillId);
            _skillVfxs = SkillVfxsTableRepo.Get(skillId);
            var owner = Context.Entity;
            //if (/*_skill.BuffTie.Length == 0*/ (ESkillVfxType)_skill.SkillVfxType is ESkillVfxType.AOE or ESkillVfxType.Trap)
            //{
            //    onCompleted(skillId, _skill.RestTime);
            //    return;
            //}
            PlayCastVfx(target);
            var isHaveBullet = PlayBullets(target);
            PlaySkillAnimation(target, isHaveBullet);
            //TODO 最少900毫秒
            var duration = _skill.EndureTime;
            //var startTime = Time.realtimeSinceStartup;
            _skillTimer = Context.Time.AddDelayTimer(duration, () =>
            {
                //Log.Debug($"SimpleSkillActor Completed. Entity:{Context.Entity.EntityId} Name:{Context.Entity.Attr.Name} SkillId:{_skill.Id} Frame:{Time.frameCount} duration:{duration}  start:{startTime} used:{Time.realtimeSinceStartup - startTime}");
                var skillCD = _skill.RestTime;
                onCompleted.SafeInvoke(skillId, skillCD);
            });
        }
        public void Stop()
        {
            _skill = null;
            _skillVfxs = null;
            _skillTimer?.Cancel();
            _skillTimer = null;
            _bulletTimer?.Cancel();
            _bulletTimer = null;
            _noAniTimer?.Cancel();
            _noAniTimer = null;
        }
        /// <summary>
        /// 播放施法特效
        /// </summary>
        /// <param name="target"></param>
        private void PlayCastVfx(ITarget target)
        {
            if (!string.IsNullOrEmpty(_skillVfxs.CastVfx))
            {
                VfxArgs vfxArgs = ObjectPool.Acquire<VfxArgs>();
                vfxArgs.vfxName = _skillVfxs.CastVfx;
                vfxArgs.duration = _skillVfxs.CastVfxTime;
                vfxArgs.followType = EVfxFollowType.CastPoint; //(EVfxFollowType)_skillVfxs.VfxFollowType;
                if (_skill.Id == 200705)
                { // TODO
                    var actFoword = ObjectPool.Acquire<ForwordAction>();
                    actFoword.forword = (target.Position - Context.Position).normalized;
                    vfxArgs.action = actFoword;
                }
                //vfxArgs.onFinish = OnSkillVfxFinish;
                Context.Vfx.Play(vfxArgs);
            }
        }
        /// <summary>
        /// 播放施法动作
        /// </summary>
        /// <param name="target"></param>
        /// <param name="isHaveBullet">是否有子弹，没子弹才需要播放受击特效</param>
        private void PlaySkillAnimation(ITarget target, bool isHaveBullet)
        {
            var actionName = _skillVfxs.AniName;
            if (actionName == EAnimationName.skill && Context.Entity.EntityType != EEntityType.Partner)
            { //TODO 现在只有随从有施法动作
                actionName = EAnimationName.attack;
            }
            //if (skill.Id == 200707)
            //{
            //    actionName = EAnimationName.skill2;
            //}
            var skillVfxTyp = (ESkillVfxType)_skill.SkillVfxType;
            void onTrigger()
            {
                _noAniTimer = null;
                if (skillVfxTyp is ESkillVfxType.Trap or ESkillVfxType.AOE or ESkillVfxType.AOENoMove or ESkillVfxType.AOETarget)
                { //播放召唤兽特效
                    SummonBeat(target);
                }
                else
                { // target不为空,播放受击特效
                    PlayHitVfx(target);
                }
            }
            if (actionName >= EAnimationName.attack)
            { // 有攻击动作
                var skillId = _skillVfxs.Id;
                var entityName = Context.Entity.Attr.Name;
                var actArgs = new AnimationPlayArgs()
                {
                    aniName = actionName,
                    //onCompleted = () =>
                    //{
                    //    Assert.IsNotNull(Context, $"技能动作回调，Context不能为空. skillId:{skillId} entityName:{entityName}");
                    //    Context.Animator.Play(EAnimationName.idle/* + UnityEngine.Random.Range(0, 100) % 2*/);
                    //}
                };
                if (!isHaveBullet)
                { // 没有子弹，300毫秒后召唤或者播放受击特效
                    actArgs.triggerFrame = _skillVfxs.SkillVfxDelay;
                    actArgs.onTrigger = onTrigger;
                }
                Context.Animator.Play(actArgs);
            }
            else if (!isHaveBullet)
            {  // 没有子弹，300毫秒后召唤或者播放受击特效
                _noAniTimer = Context.Time.AddDelayTimer(_skillVfxs.SkillVfxDelay, onTrigger);
            }
        }
        /// <summary>
        /// 播放子弹
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        private bool PlayBullets(ITarget target)
        {
            var bulletCount = _skill.SkillVfxType / 100 == 1 ? _skillVfxs.SkillVfxCount : 0;
            if (bulletCount > 0)
            { // 有子弹，设置子弹的定时器
                var targetId = target?.Entity.EntityId ?? 0;
                var to = target?.Position ?? Vector3.zero;
                _bulletTimer = Context.Time.AddDelayLooperTimer(_skillVfxs.SkillVfxDelay, _skillVfxs.SkillVfxInterval > 0 ? _skillVfxs.SkillVfxInterval : 500, (times) =>
                {
                    //XGame.Log.Debug($"Skill bullet loop Id:{skillId} Count:{bulletCount} Times:{times}");
                    if (times == bulletCount)
                        _bulletTimer = null;
                    var bulletArgs = new GenBulletDto()
                    {
                        masterId = Context.Entity.EntityId,
                        masterType = Context.Entity.EntityType,
                        targetId = targetId,
                        tableId = _skill.Id,
                        from = Context.Position,
                        to = to,
                    };
                    EventSingle.Instance.Notify(EventDefine.GameMainMapGenBullet, bulletArgs);
                }, bulletCount);
                return true;
            }
            return false;
        }
        /// <summary>
        /// 召唤技能
        /// </summary>
        private void SummonBeat(ITarget target)
        {
            var dto = new GenSummonsDto()
            {
                masterId = Context.Entity.EntityId,
                masterType = Context.Entity.EntityType,
                tableId = _skill.Id,
                from = Context.Position,
                count = _skillVfxs.SkillVfxCount
            };
            if (target != null)
            {
                dto.targetId = target.Entity.EntityId;
                dto.targetType = target.Entity.EntityType;
                dto.from = target.Position;
            }
            else
            { //TODO 根据技能配置确定目标类型
                dto.targetType = dto.masterType == EEntityType.Monster ? EEntityType.Player : EEntityType.Monster;
            }
            EventSingle.Instance.Notify(EventDefine.GameMainMapGenCommons, dto);
        }
        /// <summary>
        /// 受击特效
        /// </summary>
        /// <param name="target"></param>
        private void PlayHitVfx(ITarget target)
        {
            var to = target?.Position ?? Vector3.zero;
            var hitVfx = _skillVfxs.HitVfx;
            if (!string.IsNullOrEmpty(hitVfx))
            {
                var actPosition = ObjectPool.Acquire<PositionAction>();
                actPosition.position = to;
                var hitArgs = ObjectPool.Acquire<VfxArgs>();
                hitArgs.vfxName = _skillVfxs.HitVfx;
                hitArgs.duration = _skillVfxs.HitVfxTime; //hitEffect == "effect_sk_hit_13521" ? 3000 : 2000;
                hitArgs.followType = EVfxFollowType.World;
                hitArgs.action = actPosition;
                Context.Vfx.Play(hitArgs);
            }
            Assert.IsNotNull(target, $"PlayHitVfx target null. skill:{_skill.Id}");
            if (!target.IsDead)
            {
                target.Calculation.Damage(-_skill.Damage, Context.Entity.EntityId, _skill);
            }
        }
        void IReference.Clear()
        {
            Stop();
            Context = null;
        }
    }
}
