using FL.Battle.Actions;
using FL.Battle.Skills;
using System;
using System.Collections.Generic;
using UnityEngine;
using XGame.Database;
using XGame.Framework;
using XGame.Framework.Components;
using XGame.Framework.Time;

namespace FL.Battle.Components.AI
{
    public interface IAOEEntityAIContext
    {
        long UID { get; }
        long MasterId { get; }
        int TableId { get; }
        ITargetSelector Selector { get; }
        ITimeModule Time { get; }
        Vector3 Position { get; }
        Transform Tr { get; }
        MoveComponent Move { get; }
        VfxComponent Vfx { get; }
    }
    /// <summary>
    /// AI组件和具体的EntityView绑定，其他Component最好不要尝试获取AI组件
    /// 虫群特效半径为1，配置宽高需要X2，该特效不适合缩放，预制按照目标尺寸重复摆放基础特效
    /// </summary>
    public class AOEEntityAI : Component<IAOEEntityAIContext>
    {
        private EEntityType _targetType;
        private ITimer _aoeTimer;
        private ITimer _stopTimer;
        private SkillTable _skill;
        private SkillVfxsTable _skillVfxs;
        private List<ITarget> _targets = new List<ITarget>();
        private HashSet<long> _selectedTargetIds = new();
        private Dictionary<long, int> _targetHitTimesMap = new();

        protected override void OnDispose()
        {
            _selectedTargetIds.Clear();
            _targetHitTimesMap.Clear();
            _targets.Clear();
            _aoeTimer?.Cancel();
            _aoeTimer = null;
            _stopTimer?.Cancel();
            _stopTimer = null;
            _skill = null;
            _skillVfxs = null;
        }
        public void Start(Vector3 targetPosition, EEntityType targetType)
        {
            _skill = SkillTableRepo.Get(Context.TableId);
            _skillVfxs = SkillVfxsTableRepo.Get(Context.TableId);
            _targetType = targetType;
            //Context.ParticleTr.localScale = new Vector3(_skill.Ranges[1] * 0.5f, _skill.Ranges[2] * 0.5f, 1);
            // 飞到目标位置
            if (_skill.SkillVfxType == (int)ESkillVfxType.AOE)
            {
                var moveArgs = new MoveArgs()
                {
                    target = targetPosition,
                    speed = _skillVfxs.SkillVfxSpeed,
                    timeScale = 1,
                    onComplete = StopAOE
                };
                if (Enum.TryParse<DG.Tweening.Ease>(_skillVfxs.SkillVfxMoveEase, true, out var ease))
                {
                    moveArgs.ease = ease;
                }
                //Context.Tr.forward = (targetPosition - Context.Position).normalized;
                Context.Move.MoveTo(moveArgs);

            }
            else
            { //TODO 判断是否需要左右镜像
                Context.Tr.localScale = new Vector3(-1, 1, 1);
                _stopTimer = Context.Time.AddDelayTimer(_skillVfxs.SkillVfxTime, StopAOE);
            }
            _aoeTimer = Context.Time.AddDelayLooperTimer(_skill.DamageArgs[1], _skill.DamageArgs[2], OnAOE, _skill.DamageArgs[0]);
        }

        private void OnAOE(int obj)
        {
            // 是否重复选中，0:false
            var isSelectOnce = _skill.DamageArgs[3] == 0;
            // 受击次数，-1:不限，1:1次
            var hitLimit = _skill.DamageArgs[4];
            bool IsFilt(ITarget a)
            {
                if (isSelectOnce)
                    return _selectedTargetIds.Contains(a.Entity.EntityId);
                return false;
            }
            bool isHaveTargets;
            if (_skill.Ranges[0] == 1)
            { // 矩形
                var size = new Vector2(_skill.Ranges[1], _skill.Ranges[2]);
                Vector2 position = Context.Position;
                position -= (size * 0.5f);
                var rect = new Rect(position, size);
                isHaveTargets = Context.Selector.FindTargets(rect, _targetType, ETargetFindType.InRangeAlive, IsFilt, ref _targets);
            }
            else
            {
                var finder = new FinderInfo()
                {
                    uid = Context.UID,
                    position = Context.Position,
                    radius = _skill.Ranges[1]
                };
                isHaveTargets = Context.Selector.FindTargets(finder, _targetType, ETargetFindType.InRangeAlive, IsFilt, ref _targets);
            }
            if (isHaveTargets)
            {
                // 计算受击伤害
                foreach (var target in _targets)
                {
                    var targetId = target.Entity.EntityId;
                    var hitTimes = 0;
                    var damage = _skill.Damage;
                    if (hitLimit < 0 || _targetHitTimesMap.TryGetValue(targetId, out hitTimes) == false || hitTimes < hitLimit)
                    { // 没有有受击次数限制 或 受击次数未达到上限
                        PlayHitVfx(target.Position);
                        if (_skill.Ranges[0] == 2 && _skill.Ranges.Length == 5)
                        { // 圆形，有半径递减
                            var distance = Vector3.Distance(target.Position, Context.Position);
                            if (distance > _skill.Ranges[3])
                            {
                                // 向上取整
                                damage = Mathf.CeilToInt((1 - _skill.Ranges[4]) * damage);
                            }
                        }
                    }
                    else
                    { // 本次受击不造成伤害，但是还是要判断触发buff等
                        damage = 0;
                    }
                    //if (_skill.SkillVfxType == (int)ESkillVfxType.AOETarget)
                    //{
                    //    Log.Debug($"Skill AOE Id:{_skill.Id} target:{targetId} damage:{damage}");
                    //}
                    target.Calculation.Damage(-damage, Context.MasterId, _skill);
                    if (hitLimit > 0)
                    { // 记录目标受击次数
                        _targetHitTimesMap[targetId] = ++hitTimes;
                    }
                    if (isSelectOnce)
                        _selectedTargetIds.Add(targetId);
                }
                _targets.Clear();
            }
            //if (_skill.SkillVfxType == (int)ESkillVfxType.AOENoMove)
            //{
            //    StopAOE();
            //}
        }
        /// <summary>
        /// 受击特效
        /// </summary>
        /// <param name="targetPosition"></param>
        private void PlayHitVfx(Vector3 targetPosition)
        {
            if (string.IsNullOrEmpty(_skillVfxs.HitVfx))
                return;
            var actPosition = ObjectPool.Acquire<PositionAction>();
            actPosition.position = targetPosition;
            var hitArgs = ObjectPool.Acquire<VfxArgs>();
            hitArgs.vfxName = _skillVfxs.HitVfx;
            hitArgs.duration = _skillVfxs.HitVfxTime;
            hitArgs.followType = EVfxFollowType.World;
            hitArgs.action = actPosition;
            Context.Vfx.Play(hitArgs);
        }

        private void StopAOE()
        {
            _aoeTimer?.Cancel();
            _aoeTimer = null;
            _stopTimer?.Cancel();
            _stopTimer = null;
            EventSingle.Instance.Notify(EventDefine.GameMainMapRemoveSimpleEntity, Context.UID);
        }
    }
}
