using System;
using System.Collections.Generic;
using System.Text;
using CommonLang.Property;
using CommonLang.Formula;
using CommonLang.IO.Attribute;
using CommonLang.IO;
using CommonAI.Zone.Instance;
using CommonAI.Zone.Attributes;
using CommonLang.Xml;
using CommonAI.Zone.Formula;

namespace CommonAI.Zone.UnitTriggers
{
    public enum AttackType : byte
    {
        NormalAttack,
        SpellAttack,
        SkillAttack,
        BuffAttack,
        AllAttack,
    }
    //-------------------------------------------------------------------------------

    public abstract class BaseTriggerEvent : ICloneable, IExternalizable
    {
        abstract public bool Test(InstanceUnit unit, AttackSource source);

        abstract public object Clone();

        abstract public void WriteExternal(IOutputStream output);

        abstract public void ReadExternal(IInputStream input);
    }

    //-------------------------------------------------------------------------------

    [MessageType(0x4201)]
    [DescAttribute("单位血量", "事件-单位被攻击")]
    [UnitTriggerEventTypeAttribute(typeof(InstanceUnit.DamageHandler))]
    public class OnDamageHpChanged : BaseTriggerEvent
    {
        [DescAttribute("比较符号", "条件")]
        public NumericComparisonOP OP = NumericComparisonOP.LESS_THAN;
        [DescAttribute("HP到达的预期值", "条件")]
        public int ExpectHP;
        public override string ToString()
        {
            return string.Format("当单位被攻击且血量{0}{1}时", FormulaHelper.ToString(OP), ExpectHP);
        }
        public override bool Test(InstanceUnit unit, AttackSource source)
        {
            return FormulaHelper.Compare(unit.CurrentHP, OP, ExpectHP);
        }
        public override object Clone()
        {
            OnDamageHpChanged ret = new OnDamageHpChanged();
            ret.OP = this.OP;
            ret.ExpectHP = this.ExpectHP;
            return ret;
        }
        public override void WriteExternal(IOutputStream output)
        {
            output.PutS32((int)OP);
            output.PutS32(ExpectHP);
        }
        public override void ReadExternal(IInputStream input)
        {
            this.OP = (NumericComparisonOP)input.GetS32();
            this.ExpectHP = input.GetS32();
        }
    }

    //-------------------------------------------------------------------------------

    [MessageType(0x4202)]
    [DescAttribute("单位血量百分比", "事件-单位被攻击")]
    [UnitTriggerEventTypeAttribute(typeof(InstanceUnit.DamageHandler))]
    public class OnDamageHpPctChanged : BaseTriggerEvent
    {
        [DescAttribute("比较符号", "条件")]
        public NumericComparisonOP OP = NumericComparisonOP.LESS_THAN;
        [DescAttribute("HP到达的预期值百分比", "条件")]
        public float ExpectHP_Pct;
        public override string ToString()
        {
            return string.Format("当单位被攻击且血量{0}{1}%时", FormulaHelper.ToString(OP), ExpectHP_Pct);
        }
        public override bool Test(InstanceUnit unit, AttackSource source)
        {
            float unit_hp_pct = 100.0f * unit.CurrentHP / unit.MaxHP;
            return FormulaHelper.Compare(unit_hp_pct, OP, ExpectHP_Pct);
        }
        public override object Clone()
        {
            OnDamageHpPctChanged ret = new OnDamageHpPctChanged();
            ret.OP = this.OP;
            ret.ExpectHP_Pct = this.ExpectHP_Pct;
            return ret;
        }
        public override void WriteExternal(IOutputStream output)
        {
            output.PutS32((int)OP);
            output.PutF32(ExpectHP_Pct);
        }
        public override void ReadExternal(IInputStream input)
        {
            this.OP = (NumericComparisonOP)input.GetS32();
            this.ExpectHP_Pct = input.GetF32();
        }
    }

    //-------------------------------------------------------------------------------

    [MessageType(0x4203)]
    [DescAttribute("被攻击", "事件-单位被攻击")]
    [UnitTriggerEventTypeAttribute(typeof(InstanceUnit.DamageHandler))]
    public class OnDamageTrigger : BaseTriggerEvent
    {
        [DescAttribute("触发百分比", "条件")]
        public float Percent = 50.0f;
        public override string ToString()
        {
            return string.Format("当单位被攻击有{0}%概率", Percent);
        }

        public override bool Test(InstanceUnit unit, AttackSource source)
        {
            if (source.FromSkill != null || source.FromSpell != null)
            {
                int rd = unit.RandomN.Next(100);
                return rd < Percent;
            }
            else
            {
                return false;
            }
        }
        public override object Clone()
        {
            OnDamageTrigger ret = new OnDamageTrigger();
            ret.Percent = this.Percent;
            return ret;
        }
        public override void WriteExternal(IOutputStream output)
        {
            output.PutF32(Percent);
        }
        public override void ReadExternal(IInputStream input)
        {
            this.Percent = input.GetF32();
        }
    }

    //-------------------------------------------------------------------------------

    [MessageType(0x4204)]
    [DescAttribute("攻击", "事件-单位攻击")]
    [UnitTriggerEventTypeAttribute(typeof(InstanceUnit.AttackHandler))]
    public class OnAttackTrigger : BaseTriggerEvent
    {
        [DescAttribute("触发百分比", "条件")]
        public float Percent = 50.0f;
        [DescAttribute("攻击类型", "条件")]
        public AttackType AType = AttackType.AllAttack;

        public override string ToString()
        {
            return string.Format("当单位攻击类型为{0}时有{1}%概率", AType, Percent);
        }

        public override bool Test(InstanceUnit unit, AttackSource source)
        {
            bool isTrueAttack = false;
            switch (AType)
            {
                case AttackType.NormalAttack:
                    if (source.FromSkill != null || source.FromSpell != null)
                    {
                        isTrueAttack = true;
                    }
                    break;
                case AttackType.SkillAttack:
                    if (source.FromSkill != null)
                    {
                        isTrueAttack = true;
                    }
                    break;
                case AttackType.SpellAttack:
                    if (source.FromSpell != null)
                    {
                        isTrueAttack = true;
                    }
                    break;
                case AttackType.BuffAttack:
                    if (source.FromBuff != null)
                    {
                        isTrueAttack = true;
                    }
                    break;
                case AttackType.AllAttack:
                    isTrueAttack = true;
                    break;
                default:
                    break;
            }
            if (isTrueAttack)
            {
                int rd = unit.RandomN.Next(100);
                return rd < Percent;
            }
            else
            {
                return isTrueAttack;
            }
        }
        public override object Clone()
        {
            OnAttackTrigger ret = new OnAttackTrigger();
            ret.Percent = this.Percent;
            ret.AType = this.AType;
            return ret;
        }
        public override void WriteExternal(IOutputStream output)
        {
            output.PutS32((int)AType);
            output.PutF32(Percent);
        }
        public override void ReadExternal(IInputStream input)
        {
            byte atype = (byte)input.GetS32();
            this.AType = (AttackType)atype;
            this.Percent = input.GetF32();
        }
    }

}