using CommonAI.Data;
using CommonAI.Zone;
using CommonAI.Zone.Formula;
using CommonAI.ZoneServer.JSGModule;
using CommonLang;
using NPOI.SS.Formula;
using System;
using System.Collections.Generic;
using XmdsCommon.Message;
using XmdsCommon.Plugin;
using XmdsCommonServer.Plugin.Scene;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.DamageCalculator;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.Skills;
using XmdsCommonServer.XLS;
using XmdsCommonServer.XLS.Data;

namespace XmdsCommonServer.Plugin
{
    /// <summary>
    /// FileName: XmdsVirtual.cs
    /// Author: Alex.Yu
    /// Corporation:... 
    /// Description: 用于伤害数值计算.
    /// DateTime: 2015/5/13 14:17:23
    /// </summary>
    partial class XmdsVirtual
    {

        /// <summary>
        /// 攻击结果.
        /// </summary>
        public enum UnitHitEventState
        {
            Normal = 0,					//普通攻击.
            Crit = 1,					//暴击.
            Dodge = 2,					//闪避.
            Parry = 3,					//招架.
            Absorb = 4,					//吸收.
            Immunity = 5,				//免疫.
            IronMaiden = 6,				//反伤.
            MP = 7,						//法力.
			KillMonsterCrit = 8,		//斩妖系统暴击	
        }

        /// <summary>
        /// 攻击结果:暴击、闪避、普通伤害.
        /// </summary>
        public enum AttackRlt : int
        {
            NoControl = -1,
            NormalAttack,
            CritAttack,
            ParryAttack,

        }

        //单位vs单位计算hit计算.
        private int On_hit_unit_vs_unit(XmdsVirtual attacker, XmdsVirtual hitter, AttackSource source, ref AtkResult result)
        {

            source.OutClientState = (int)UnitHitEventState.Normal;

            //是否为技能.
            bool isSkill = source.FromBuffState == null ? true : false;

            int damage = 0;

            //result.rlt = AttackRlt.NormalAttack;

            if (isSkill == false)
            {
                BuffTemplate template = source.FromBuffState.Data;
                //XmdsBuffProperties prop = template.Properties as XmdsBuffProperties;
                List<XmdsBuffVirtual> list = source.FromBuffState.Tag as List<XmdsBuffVirtual>;
                if (list != null)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        UnitBuff ub = list[i] as UnitBuff;
                        damage += ub.BuffHit(hitter, attacker, source, ref result);
                    }
                }

                //分发事件单位收到伤害.
                damage = (int)hitter.DispatchHitDamageEvent(damage, attacker, source,ref result, template.IsHarmful ? DamageType.Damage : DamageType.Heal);
            }
            else
            {
                //1.计算攻击结果.2计算攻击伤害.
                damage = CalDamage(attacker, hitter, source, ref result);
            }


			damage += source.Attack.Attack;

			//设置结果.
			switch (source.OutClientState)
            {
                case (int)UnitHitEventState.Dodge:
                    //source.OutClientState = (int)UnitHitEventState.Dodge;
                    XmdsAttackProperties prop = (source.Attack.Properties as XmdsAttackProperties);
                    FormatLog("{0}对目标{1}使用技能【{2}】被目标【闪避】", attacker.mInfo.Name, hitter.mInfo.Name, prop.SkillTemplateID);
                    damage = 0;
                    break;
                case (int)UnitHitEventState.Crit:
                    //source.OutClientState = (int)UnitHitEventState.Crit;
                    FormatLog("【{0}】攻击【{1}】结果 =【{2}】,伤害 =【{3}】", attacker.mInfo.Name, hitter.mInfo.Name, "暴击", damage);
                    break;
                case (int)UnitHitEventState.Normal:
                    //source.OutClientState = (int)UnitHitEventState.Normal;
                    FormatLog("【{0}】攻击【{1}】结果 =【{2}】,伤害 =【{3}】", attacker.mInfo.Name, hitter.mInfo.Name, "普攻", damage);
                    break;
                case (int)UnitHitEventState.Immunity:
                    //source.OutClientState = (int)UnitHitEventState.Normal;
                    FormatLog("【{0}】攻击【{1}】结果 =【{2}】,伤害 =【{3}】", attacker.mInfo.Name, hitter.mInfo.Name, "免疫", damage);
                    break;
                case (int)UnitHitEventState.Absorb:
                    //source.OutClientState = (int)UnitHitEventState.Normal;
                    FormatLog("【{0}】攻击【{1}】结果 =【{2}】,伤害 =【{3}】", attacker.mInfo.Name, hitter.mInfo.Name, "吸收", damage);
                    break;
                case (int)UnitHitEventState.IronMaiden:
                    //source.OutClientState = (int)UnitHitEventState.Normal;
                    FormatLog("【{0}】攻击【{1}】结果 =【{2}】,伤害 =【{3}】", attacker.mInfo.Name, hitter.mInfo.Name, "反伤", damage);
                    break;
                default:
                    break;
            }

            if (damage == 0)
            {
                //闪避时不产生受击.
                //source.OutIsDamage = false;
            }
			else
			{
				hitter.mUnit.mLastDamageTime = CommonLang.CUtils.localTimeMS;
				attacker.mUnit.mLastHitOtherTime = CommonLang.CUtils.localTimeMS;
			}

            return damage;
        }

        /// <summary>
        /// 纷发单位打到其他单位,其他单位被攻击,(XmdsSkillBase调用).
        /// </summary>
        /// <param name="damage"></param>
        /// <param name="attacker"></param>
        /// <param name="hitter"></param>
        /// <param name="source"></param>
        public void DispatchHitEvents(ref int damage, XmdsVirtual attacker, XmdsVirtual hitter, AttackSource source, 
            ref XmdsVirtual.AtkResult result, DamageType damageType)
        {
			//分发事件单位打到别人.
			damage = (int)attacker.DispatchHitOtherEvent(damage, hitter, source, ref result, damageType);

			//分发事件单位收到伤害.
			damage = (int)hitter.DispatchHitDamageEvent(damage, attacker, source, ref result, damageType);

			//分发卡牌时间
			attacker.mCardModule.OnHitOther(hitter, source);
			hitter.mCardModule.OnHitDamage(attacker, source);
		}

        private int CalDamage(XmdsVirtual attacker, XmdsVirtual hitter, AttackSource source, ref AtkResult result)
        {
            int ret = 0;

			//攻击者调用计算伤害.
			attacker.DispatchSkillDamageEvent(attacker, hitter, source);
			ret = attacker.DispatchCalDamageEvent(hitter, source, ref result);

            return ret;
        }

        /// <summary>
        /// 伤害计算扩展类.
        /// </summary>
        public struct AtkResult
        {
            ///// <summary>
            ///// 攻击结果.
            ///// </summary>
            //public AttackRlt rlt;
            public int ThreatValue { get; set; }

            /// <summary>
            /// 更改百分比.
            /// </summary>
            public int ThreatValueChangePer { get; set; }

            /// <summary>
            /// 更改绝对值.
            /// </summary>
            public int ThreatValueChangeModify { get; set; }

			//破定值
			public int breakShieldValue;
        }

		protected void dynamicCalcBy(XmdsUnitProp ret, float hp, float atk, float def, float crit, float CritDamage, float ignoreDef)
		{
			ret.BaseMaxHP = (int)(ret.BaseMaxHP * hp);
			ret.BaseAttack = (int)(ret.BaseAttack * atk);
			ret.BaseDefence = (int)(ret.BaseDefence * def);
			ret.CritRate = (int)(ret.CritRate * crit);
			ret.CritDamage = (int)(ret.CritDamage * CritDamage);
			ret.IgnoreDefensePer = (int)(ret.IgnoreDefensePer * ignoreDef);
		}

		protected void restoreMa2Ret(XmdsUnitProp ret, MonsterData ma)
		{
			if (ma.MaxHP != -1)
			{
				ret.BaseMaxHP = ma.MaxHP;
			}

			if (ma.MaxAttack != -1)
			{
				ret.BaseAttack = ma.MaxAttack;
			}

			if (ma.MaxDefence != -1)
			{
				ret.BaseDefence = ma.MaxDefence;
			}

			if (ma.CritRate != -1)
			{
				ret.CritRate = ma.CritRate;
			}

			if (ma.CritDamage != -1)
			{
				ret.CritDamage = ma.CritDamage;
			}

			if (ma.IgnoreDefencePer != -1)
			{
				ret.IgnoreDefensePer = ma.IgnoreDefencePer;
			}
		}

		protected void initProp(MonsterProp prop, MonsterData ma, XmdsUnitProp ret)
		{
			ret.BaseMaxHP = prop.MaxHP;
			ret.HP = prop.MaxHP;

			ret.BaseAttack = prop.Attack;
			ret.BaseDefence = prop.Def;
			ret.CritRate = prop.CritRate;
			ret.CritDamage = prop.CritDamage;
			ret.IgnoreDefensePer = prop.IgnoreDefensePer;

			this.mProp.ServerData.BaseInfo.UnitLv = prop.Mon_Level;
			this.mUnit.Level = prop.Mon_Level;
		}

		protected void initProp2(MonsterData ma, OrigData oData, UserDefineConfig udc, XmdsUnitProp ret)
		{
			UserDefineConfig config = XmdsDataMgr.GetInstance().mMonsterDynamicLoader.GetUserDefineConfig(ma.Type);
			float atkTemp = oData.Atk * config.Atk_Ratio;
			float defTemp = oData.Def * config.Def_Ratio;
			float hpTemp = oData.Hp * config.HP_Ratio;
			float critTemp = oData.CritRate * config.Crit_Ratio;
			float critDamageTemp = oData.CritDamage * config.CritDamage_Ratio;
			float ignoreDefTemp = oData.IgnoreDefensePer * config.IgnoreDef_Ratio;
			//防御值 * (1 — 穿透值)
			float drdaTemp1 = defTemp * (1 - ignoreDefTemp / XmdsDamageCalculator.PERER);
			//暴击值 * 爆伤值 + 1 - 暴击值
			float drdaTemp2 = (critTemp / XmdsDamageCalculator.PERER * critDamageTemp / XmdsDamageCalculator.PERER + 1
				- critTemp / XmdsDamageCalculator.PERER);
			//XmdsDamageCalculator.GetDefByLevel是获得该等级的防御基础值。人物的那个映射表
			// 43428, 43428, 45437, 47936, 50852, 54111, 57633, 61315, 65018, 68550, 71651, 73963, 75000
			float drda = 1 - (drdaTemp1 / (drdaTemp1 + XmdsDamageCalculator.GetDefByLevel(ma.Level)));

			ret.BaseMaxHP = (int)(ma.Fight_Count * ma.AliveTime * atkTemp * drda * drdaTemp2);

			float hpParma = ma.KillPlayerTime;// * drda * drdaTemp2;
			ret.BaseAttack = (int)(hpParma == 0 ? hpTemp : (hpTemp / hpParma));

			ret.BaseDefence = (int)defTemp;
			ret.CritRate = (int)(critTemp);
			ret.CritDamage = (int)(critDamageTemp);
			ret.IgnoreDefensePer = (int)(ignoreDefTemp);
		}
	}
}