using Games.GlobeDefine;
using GCGame.Table;
using Module.Log;
using System.Collections.Generic;
using UnityEngine;

namespace Games.SkillModle
{
    public enum SKILLSELLOGIC
    {
        SELLOGIC_INVALID = -1,
        SELLOGIC_SINGLE = 0,
        SELLOGIC_MULTI = 1,
        SELLOGIC_ALL = 2
    }

    public enum SKILLUSEFAILTYPE
    {
        CE_ERROR_ELSE = -1, //其他错误
        CE_OK = 0, //技能释放成功
        CE_TARGET_ERROR = 1, //技能释放目标错误
        CE_NO_SKILLEX_CONFIG = 2, //SkillEx未配置
        CE_NO_SKILLBASE_CONFIG = 3, //SkillBase未配置
        CE_IN_ESCORT_SKILL_LIMIT = 4, //跑商不能使用位移技能
        CE_IN_BUFF_LIMIT_SKILL = 5, //有buff限制技能BuffLimitSkill.txt
        CE_SCENE_INVALID = 6, //场景无效
        CE_MOUNT_FREEZE = 7, //上下马冻结期不能使用技能
        CE_SKILL_CONDI_CHECK_FAILED = 8, //技能释放条件检测未通过
        CE_IN_DEATH = 9, //死亡状态不能释放技能
        CE_ROLE_NOT_ACTIVE = 10, //角色未激活
        CE_IS_PASSIVITY = 11, //被动技能不能主动释放
        CE_IN_MAINSCENE = 12, //主城不能释放技能
        CE_SCENE_NOT_ALLOWED_XP_SKILL = 13, //当前场景不能使用xp技能
        CE_CUR_SKILL_CANNOT_BREAK = 14, //正在使用的技能不能被打断
        CE_NOT_HAVE_THIS_SKILL = 15, //没有学习该技能
        CE_IMPACT_SKILL_DISABLED = 16, //有禁止使用该技能的buff
        CE_TARGET_IN_HIDING = 17, //不能对隐身目标使用技能
        CE_DISTANCE_NOT_ENOUGH = 18, //距离不够
        CE_SCENE_NOT_ALLOWED_PK = 19, //当前场景不能PK
        CE_SCENE_NOT_ALLOWED_ATK_NEW_ROLE = 20, //新手保护
        CE_TARGET_ROLE_CANNOT_PK = 21, //目标角色不满足PK条件
        CE_PUBLIC_CD_NOT_COOL = 22, //公共CD未冷却
        CE_SKILL_CD_NOT_COOL = 23, //技能CD未冷却
        CE_BACKSWINGCD1_NOT_COOL = 24, //后摇CD1未冷却
        CE_BACKSWINGCD2_NOT_COOL = 25, //后摇CD2未冷却
        CE_SKILL_DES_POS_CHECK_FAILED = 26, //技能释放点检测失败
        CE_DEPLETE_CHECK_FAILED = 27, //技能消耗检测失败
        CE_IS_NOT_WANTED_UNIT = 28, // 非技能预期目标
        CE_SKILL_STAGE_CHECK_FAILED = 29, // 连段技能判断失败
        CE_SKILL_HAS_TYPE_SKILL_LIMIT = 30 // 技能使用时,角色状态不对
    }

    public enum SKILLFINISHREASON
    {
        BREAK = 1,
        FINISH = 2
    }

    public enum SKILLUSETYPE
    {
        SHUNFA = 0, //瞬发
        YINCHANG = 1, //吟唱
        BEIDONG = 2 //被动
    }

    public enum SKILLBASEID
    {
        XFZBASEID = 104, //摩诃无量的的baseID
        YTWJID = 307, //以退为进baseID
        YGSDID = 204, //阳关三叠baseID
        HDWLID = 306, //画地为牢 
        ZLZ = 404 //祝融掌
    }

    public enum SKILLDEFINE
    {
        MAX_SKILLNUM = 20, //主角最大技能数
        MAX_PET_SKILLNUM = 2, //宠物最大技能数
        PUBLICCDID = 14 //公共冷却ID
    }

    //每个int位表示一种类别 符合两种及以上的累加
    public enum SKILLCLASS
    {
        ACTIVE = 1, //主动技
        PASSIVITY = 2, //被动技
        AUTOREPEAT = 4, //自动连续技
        XP = 8, //XP技
        CHONGFENG = 16, //冲锋技
        DUTIAO = 32, //读条
        MASTERSKILL = 64, //师门技能
        GAINSKILL = 128, //加持技能
        SIMPLEATTACK = 256, //普攻技能
        SPECIALSKILL = 512 //玄女锁链连续技
    }

    //技能范围特效 类别
    public enum SKILLRANGEEFFECTTYPE
    {
        INVALID = -1,
        RING = 0, //环
        CIRCLE = 1, //圆
        RECT = 2, //矩形
        ARROWS = 3 //箭头
    }

    public enum SKILLRANGEEFFECTTAR
    {
        INVAILD = -1,
        SELF = 0, //自身
        SELECTTARGET = 1 //选中目标
    }

    public enum SKILLRANGEEFFECTID
    {
        INVALID = -1,
        RINGEFFECTID = 100, //环
        CIRCLEEFFECTID = 101, //圆
        RECTEFFECTID = 102, //矩形
        ARROWSEFFECTID = 103 //箭头
    }

    public class OwnSkillData
    {
        /// <summary>
        ///     总技能释放间隔时间
        /// </summary>
        public float Cooldown { get; private set; }
        /// <summary>
        ///     当前技能释放间隔时间
        /// </summary>
        public float CurrentCooldown
        {
            get { return Mathf.Max(0f, _currentCooldown); }
        }
        /// <summary>
        /// 真实的cd残余时间,可能小于0 - 以允许部分需要cd结束再延迟的检查正常使用
        /// </summary>
        private float _currentCooldown;

        // ******** 连段技能的记录 ********
        // 注:连段技能由客户端实行数据预测,不等服务器返回再更新
        /// <summary>
        /// 当前连段开始时间
        /// </summary>
        private float _comboStartTime = float.NegativeInfinity;
        /// <summary>
        /// 连段到下一段所需时间
        /// </summary>
        public float ComboTime { get; private set; }
        /// <summary>
        /// 连读残余允许时间
        /// </summary>
        public float ComboRemain
        {
            get
            {
                UpdateCombo();
                // 注:如果Combo超时,UpdateCombo后_comboStartTime会重置
                if (_comboStartTime < 0f)
                    return float.NegativeInfinity;
                else
                    return _comboStartTime + ComboTime - Time.time;
            }
        }
        /// <summary>
        /// 技能cd流逝速度校正值列表
        /// </summary>
        private List<MyTuple<int, float>> _cooldownModifiers;
        /// <summary>
        /// 当前cd时间流逝速度
        /// </summary>
        public float CooldownModifier { get; private set; }
        /// <summary>
        /// 当前最后一次连段是否已经执行
        /// </summary>
        public bool FullCombo { get; private set; }

        public int exSkillLevel { get; private set; }
        public int SkillId { get; private set; }

        public void SetSkillId(int newExId, int newExLevel)
        {
            // SkillBase是否更新为其他技能
            var newSkill = false;
            if (SkillId != newExId)
            {
                var inCombo = ComboExTable != SkillExTable;
                SkillExTable = newExId < 0 ? null : TableManager.GetSkillExByID(newExId, 0);
                if (SkillExTable != null)
                {
                    if (SkillBaseTable == null || SkillBaseTable.Id != SkillExTable.BaseId)
                    {
                        newSkill = true;
                        SkillBaseTable = TableManager.GetSkillBaseByID(SkillExTable.BaseId, 0);
                    }

                    if (inCombo)
                    {
                        ComboExTable = TableManager.GetSkillExByID(SkillExTable.MultiNextSkillId, 0);
                        if (ComboExTable != null)
                            ComboBaseTable = TableManager.GetSkillBaseByID(ComboExTable.BaseId, 0);
                        else
                        {
                            ComboExTable = SkillExTable;
                            ComboBaseTable = SkillBaseTable;
                            LogModule.ErrorLog(string.Format("技能Ex{0}无法正确获得连段技能!", SkillExTable.SkillExID));
                        }
                    }
                    else
                    {
                        ComboExTable = SkillExTable;
                        ComboBaseTable = SkillBaseTable;
                    }
                }
                else
                {
                    SkillBaseTable = null;
                    ComboExTable = null;
                    ComboBaseTable = null;
                }
            }
            // 试图更新当前的Ex等级
            if (SkillId != newExId || exSkillLevel != newExLevel)
            {
                if (SkillExTable == null)
                {
                    ComboExTableFinal = null;
                    BaseExTableFinal = null;
                    SkillLevelTable = null;
                    Cooldown = default(float);
                }
                else
                {
                    if (newExLevel > 0)
                    {
                        BaseExTableFinal = TableManager.GetSkillExByID(SkillExTable.SkillExID + newExLevel, 0) ??
                                           CommonUtility.GetSkillMaxLevelByBaseId(SkillExTable.BaseId);
                        ComboExTableFinal = SkillExTable == ComboExTable ? BaseExTableFinal : TableManager.GetSkillExByID(BaseExTableFinal.MultiNextSkillId, 0);
                    }
                    else
                    {
                        ComboExTableFinal = ComboExTable;
                        BaseExTableFinal = SkillExTable;
                    }
                    SkillLevelTable = TableManager.GetSkillLevelUpByID(BaseExTableFinal.SkillExID, 0);
                    var cdTable = TableManager.GetCoolDownTimeByID(BaseExTableFinal.CDTimeId, 0);
                    Cooldown = cdTable.CDTime.ToClientTime();
                }
            }
            if (newSkill)
            {
                _currentCooldown = float.NegativeInfinity;
                _cooldownModifiers = new List<MyTuple<int, float>>();
                SetCooldownRate();
                CleanComboState();
            }

            SkillId = SkillExTable == null ? GlobeVar.INVALID_ID : SkillExTable.SkillExID;
            exSkillLevel = newExLevel;
        }

        // 连段技能的第一段数据表 - 不会受到ExSkillLevel校正
        public Tab_SkillEx SkillExTable { get; private set; }
        public Tab_SkillBase SkillBaseTable { get; private set; }
        // 当前连段技能Base数据表
        // 注:连段现在不可支持两段以上连段的情况,支持两段以上需要很多特殊处理
        public Tab_SkillEx _comboextable;
        public Tab_SkillEx ComboExTable { get; private set; }

        public Tab_SkillBase ComboBaseTable { get; private set; }
        // 受到加成修正之后的数据表
        public Tab_SkillEx BaseExTableFinal { get; private set; }
        public Tab_SkillEx ComboExTableFinal { get; private set; }

        public Tab_SkillLevelUp SkillLevelTable { get; private set; }

        public int PriorityAutoCombat
        {
            get { return ComboBaseTable == null ? 0 : ComboBaseTable.PriorityAutoFight; }
        }

        public bool IsValid()
        {
            return SkillId > -1;
        }
        /// <summary>
        /// 该技能是否为连段技能
        /// </summary>
        public bool IsComboSkill()
        {
            return SkillExTable.HasNextCombo();
        }
        /// <summary>
        ///     是否Cd结束,允许添加额外等待时间
        /// </summary>
        public bool IsCooldownFinish(float extraTime = 0f)
        {
            return _currentCooldown + extraTime <= 0f;
        }
        /// <summary>
        ///     设置技能当前释放间隔时间
        /// </summary>
        public void SetCooldown(float currentCooldown)
        {
            // 若技能进入cd(由于服务器同步信息或其他原因),技能连段重置
            if (currentCooldown > 0)
                CleanComboState();
            _currentCooldown = currentCooldown;
        }
        /// <summary>
        ///     设置技能刚刚被释放
        /// </summary>
        public void ResetCooldown()
        {
            _currentCooldown = Cooldown;
            //if (SkillBaseTable != ComboBaseTable)
            CleanComboState();
        }
        /// <summary>
        /// 更新技能冷却时间
        /// </summary>
        public void UpdateCooldown()
        {
            if (IsValid())
                _currentCooldown -= Time.unscaledDeltaTime * CooldownModifier;
        }

        private void SetCooldownRate()
        {
            CooldownModifier = 1f;
            for (var i = 0; i < _cooldownModifiers.Count; i++)
                CooldownModifier *= _cooldownModifiers[i].second;
        }
        /// <summary>
        /// 增加一个技能冷却校正
        /// </summary>
        public void AddCooldownModifier(int handle, float value)
        {
            if (IsValid())
            {
                _cooldownModifiers.Add(new MyTuple<int, float>(handle, value));
                SetCooldownRate();
            }
        }
        /// <summary>
        /// 移除一个技能冷却校正
        /// </summary>
        public void RemoveCooldownModifier(int handle)
        {
            if (IsValid())
            {
                var index = _cooldownModifiers.FindIndex(a => a.first == handle);
                if (index >= 0)
                {
                    _cooldownModifiers.RemoveAt(index);
                    SetCooldownRate();
                }
            }
        }
        /// <summary>
        /// 立刻减少cd时间
        /// </summary>
        public void SubstractCooldown(float time)
        {
            if (IsValid())
                _currentCooldown -= time * CooldownModifier;
        }
        /// <summary>
        /// 清除当前技能
        /// </summary>
        public void CleanUp()
        {
            SkillId = -1;
            _currentCooldown = float.NegativeInfinity;
            CleanComboState();
        }
        //  注:一般调用这个技能前,应该已经进行过一次UpdateCombo操作,因此不判定连段跌落的情况
        public void AddCombo()
        {
            if (!SkillBaseTable.SkillClass.ContainFlag((int)SKILLCLASS.SIMPLEATTACK))
            {
                // 如果当前技能仍然可以连段
                if (ComboExTable.HasNextCombo())
                {
                    //var cdTable = TableManager.GetCoolDownTimeByID(ComboExTable.NextSkillCDTimeId, 0);
                    //ComboTime = 3.0f;//cdTable.CDTime.ToClientTime();
                    //int use_multi_id = 0;
                    var base_id = ComboExTable.NextStageSkillId;
                    if (base_id > 0)
                    {
                        var ownSkill = GameManager.gameManager.PlayerDataPool.GetOwnSkillInfo(base_id);
                        //use_multi_id = ownSkill.SkillId;
                        if (ownSkill != null)
                        {
                            ownSkill.ComboTime = 3.0f;
                            ownSkill._comboStartTime = Time.time;
                        }
                    }

                    //ComboExTable = TableManager.GetSkillExByID(use_multi_id, 0);
                    //ComboExTableFinal = TableManager.GetSkillExByID(use_multi_id, 0);
                    ////ComboExTable = TableManager.GetSkillExByID(ComboExTable.MultiNextSkillId, 0);
                    ////ComboExTableFinal = TableManager.GetSkillExByID(ComboExTableFinal.MultiNextSkillId, 0);
                    //ComboBaseTable = TableManager.GetSkillBaseByID(ComboExTable.BaseId, 0);
                    //_comboStartTime = Time.time;
                    _currentCooldown = Cooldown;
                }
                else
                    FullCombo = true;
                //{
                //    // 如果技能是连段技能回滚到第一段,增加一次假cd时间
                //    if (ComboExTable != SkillExTable)
                //        CleanComboState();
                //}
            }
        }

        public OwnSkillData GetComboSkill()
        {
            if (!SkillBaseTable.SkillClass.ContainFlag((int)SKILLCLASS.SIMPLEATTACK))
            {
                if (ComboExTable.HasNextCombo())
                {
                    var base_id = ComboExTable.NextStageSkillId;
                    if (base_id > 0)
                    {
                        return GameManager.gameManager.PlayerDataPool.GetOwnSkillInfo(base_id);
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// 更新连段状态
        /// </summary>
        public void UpdateCombo()
        {
            // 普攻不使用Combo逻辑
            // 非连段不使用Combo逻辑
            if (!SkillBaseTable.SkillClass.ContainFlag((int)SKILLCLASS.SIMPLEATTACK)
               )// && IsComboSkill()
            {
                // Combo衔接超时的情况,特殊预测当前连段
                // 注:客户端会先走预测Cooldown,然后等待服务器返回的真实Cooldown
                if (ComboExTable != SkillExTable && (_comboStartTime < 0f || _comboStartTime + ComboTime < Time.time))
                {
                    ResetCooldown();
                    //CleanComboState();
                }
            }
        }

        public void CleanComboState()
        {
            ComboTime = 0f;
            ComboExTable = SkillExTable;
            ComboExTableFinal = BaseExTableFinal;
            ComboBaseTable = SkillBaseTable;
            _comboStartTime = float.NegativeInfinity;
            FullCombo = false;
        }
    }

    public struct ShowDamageInfo
    {
        public int showValue;
        public int showTime;
        public float interval;
        public Tab_DamageBoardType damageType;
        public float nextShowTime;
    }
    /// <summary>
    /// 用于GC_SYN_SKILLINFO的临时数据
    /// </summary>
    // 注:由于协议是动态生成的,因此暂时
    public struct SyncSkillData
    {
        public int index;
        public int skillId;
        public int skillBaseId;
        public float cooldown;
    }

    //public struct MultiShowDamageBoard //多次显示 
    //{
    //    public void CleanUp()
    //    {
    //        ShowValue = 0;
    //        ShowTimes = -1;
    //        ShowInter = -1.0f;
    //        DamageType = GameDefine_Globe.DAMAGEBOARD_TYPE.PLAYER_TYPE_INVALID;
    //        NextShowTime = 0;
    //    }
    //
    //    public int ShowValue { get; set; }
    //
    //    public int ShowTimes { get; set; }
    //
    //    public float ShowInter { get; set; }
    //
    //    public GameDefine_Globe.DAMAGEBOARD_TYPE DamageType { get; set; }
    //
    //    public float NextShowTime { get; set; }
    //}
}