using System;
using System.Collections.Generic;
using System.Text;
using CommonLang.Property;
using CommonAI.Zone.Attributes;
using CommonAI.Zone.Instance;
using CommonLang.IO;
using CommonLang.IO.Attribute;
using CommonAI.data;
using CommonAI.Data;

namespace CommonAI.Zone.ZoneEditor
{
    [TableClassAttribute("Name")]
    public abstract class AbilityData : IExternalizable
    {
        [DescAttribute("Name", "", true)]
        public string Name;
        public override string ToString()
        {
            if (string.IsNullOrEmpty(Name))
            {
                return base.ToString();
            }
            else
            {
                return Name;
            }
        }
        public virtual void WriteExternal(IOutputStream output)
        {
            output.PutUTF(this.Name);
        }
        public virtual void ReadExternal(IInputStream input)
        {
            this.Name = input.GetUTF();
        }
    }
    public abstract class SceneAbilityData : AbilityData { }
    public abstract class UnitAbilityData : AbilityData { }
    public abstract class ItemAbilityData : AbilityData { }
    public abstract class RegionAbilityData : AbilityData { }
    public abstract class DecorationAbilityData : AbilityData { }
    public abstract class PointAbilityData : AbilityData { }
    public abstract class AreaAbilityData : AbilityData { }


    [MessageType(0x4401)]
    [DescAttribute("玩家出生点")]
    public class PlayerStartAbilityData : RegionAbilityData
    {
        [DescAttribute("阵营")]
        public int START_Force;

        [DescAttribute("测试主角ID", "测试", true)]
        [TemplateIDAttribute(typeof(UnitInfo))]
        public int TestActorTemplateID = 1;

        [TemplateLevelAttribute]
        public int TestActorLevel;

        public override string ToString()
        {
            return "玩家出生点: " + START_Force;
        }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(START_Force);
            output.PutS32(TestActorTemplateID);
            output.PutS32(TestActorLevel);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.START_Force = input.GetS32();
            this.TestActorTemplateID = input.GetS32();
            this.TestActorLevel = input.GetS32();
        }
    }

    [MessageType(0x4402)]
    [DescAttribute("怪物刷新点")]
    public class SpawnUnitAbilityData : RegionAbilityData
    {
        [MessageType(0x4403)]
        [DescAttribute("怪物刷新ID和等级")]
        public class SpawnUnit : IExternalizable
        {
            [DescAttribute("单位模板")]
            [TemplateIDAttribute(typeof(UnitInfo))]
            public int UnitTemplateID;
            [DescAttribute("单位等级")]
            [TemplateLevelAttribute]
            public int UnitLevel = 0;
            [DescAttribute("此单位每次刷新概率百分比")]
            public float Percent = 100f;
            public override string ToString()
            {
                return UnitTemplateID.ToString();
            }
            public  void WriteExternal(IOutputStream output)
            {
                output.PutS32(UnitTemplateID);
                output.PutS32(UnitLevel);
                output.PutF32(Percent);
            }
            public  void ReadExternal(IInputStream input)
            {
                this.UnitTemplateID = input.GetS32();
                this.UnitLevel = input.GetS32();
                this.Percent = input.GetF32();
            }
        }
        [DescAttribute("怪物类型模板ID和等级组(新功能)", "基础")]
        public List<SpawnUnit> UnitTemplates = new List<SpawnUnit>();

        [DescAttribute("怪物类型模板ID组(兼容老版本)", "基础")]
        [TemplatesIDAttribute(typeof(UnitInfo))]
        public List<int> UnitTemplatesID = new List<int>();

        [DescAttribute("怪物等级", "可选")]
        [TemplateLevelAttribute]
        public int UnitLevel;
        [DescAttribute("延迟启动时间(毫秒)", "可选")]
        public int StartTimeDelayMS;
        [DescAttribute("刷新间隔时间(毫秒)", "基础")]
        public int IntervalMS = 5000;
        [DescAttribute("一次刷新数量", "基础")]
        public int OnceCount = 5;
        [DescAttribute("总刷新数量上限(0表示无上限)", "可选")]
        public int TotalLimit;
        [DescAttribute("存活数量上限(0表示无上限)", "可选")]
        public int AliveLimit;
        [DescAttribute("每次刷新必须所有怪物死亡", "基础")]
        public bool WithoutAlive;
        [DescAttribute("怪物初始阵营", "基础")]
        public byte Force;
        [DescAttribute("怪物初始标记", "可选")]
        public string UnitTag;
        [DescAttribute("怪物名字", "可选")]
        public string UnitName;
		[DescAttribute("随机阵营-下限", "可选")]
		[DependOnProperty("NotPointForce")]
		public byte forceMin;
		[DescAttribute("随机阵营-上限", "可选")]
		[DependOnProperty("NotPointForce")]
		public byte forceMax;

		[DescAttribute("怪物没有存活时,重置刷新点计时(间隔时间用StartTimeDelayMS控制)", "基础")]
        public bool ResetOnWithoutAlive;

		public bool NotPointForce() { return this.Force == 0; }

		[SceneObjectIDAttribute(typeof(PointData))]
        [DescAttribute("怪物初始路点", "路点")]
        public string StartPointName;
        [DescAttribute("切换路点待机最小时间(毫秒)", "路点")]
        public int StartPathHoldMinTimeMS = 0;
        [DescAttribute("切换路点待机最大时间(毫秒)", "路点")]
        public int StartPathHoldMaxTimeMS = 0;
		[DescAttribute("和平时间", "路点")]
		public int PeaceTime = 0;

		[DescAttribute("初始朝向(大于等于0有效)", "可选")]
        public float StartDirection = -1;

        [DescAttribute("怪物产生时触发的特效", "资源")]
        public LaunchEffect SpawnEffect;

        [DescAttribute("一次刷新多个怪物时初始阵型", "阵型")]
        public TeamFormation TFormation;

		//[MessageType(0x4408)]
		//[DescAttribute("绑定单位事件集合")]
		//public class BindEvent : IExternalizable
		//{
		//	[SceneEventIDAttribute]
		//	[DescAttribute("触发事件名字")]
		//	public string EventName;

		//	public override string ToString()
		//	{
		//		return EventName;
		//	}
		//	public void WriteExternal(IOutputStream output)
		//	{
		//		output.PutUTF(EventName);
		//	}
		//	public void ReadExternal(IInputStream input)
		//	{
		//		this.EventName = input.GetUTF();
		//	}
		//}
		//[DescAttribute("单位绑定触发事件(编辑器中绑定)", "事件")]
		//public List<BindEvent> Events = new List<BindEvent>();

		public override string ToString()
        {
            int count = UnitTemplatesID.Count;
            if (UnitTemplates != null)
            {
                count += UnitTemplates.Count;
            }
            return "怪物刷新点: " + count + "种类型";
        }

		public byte GetForce()
		{
			if(this.Force == 0 && this.forceMax > this.forceMin && this.forceMin >= 0)
			{
				return (byte)(GlobalData.gRandom.Next() % (this.forceMax - this.forceMin) + this.forceMin);
			}

			return this.Force;
		}

        public SpawnUnitTrigger CreateTrigger(EditorScene scene)
        {
            SpawnUnitTrigger tg = new SpawnUnitTrigger(scene, this.Name);
            tg.setDelayTime(this.StartTimeDelayMS);
            tg.setSpawnInterval(this.IntervalMS);
            tg.setSpawnCount(this.OnceCount);
            tg.setSpawnEffect(this.SpawnEffect);
            tg.setLimitedAliveCount(this.AliveLimit);
            tg.setLimitedSpawnCount(this.TotalLimit);
            tg.setSpawnWithoutAlive(this.WithoutAlive);
            tg.setUnitTag(this.UnitTag);
            tg.setUnitName(this.UnitName);
			if(this.Force > 0)
			{
				tg.setUnitForce(this.Force, this.Force);
			}
			else
			{
				tg.setUnitForce(this.forceMin, this.forceMax);
			}
            
            tg.addUnits(this.UnitTemplatesID.ToArray(), this.UnitLevel);
            if (UnitTemplates != null)
            {
                foreach (SpawnUnit spawn in this.UnitTemplates)
                {
                    tg.addUnitInfo(spawn.UnitTemplateID, spawn.UnitLevel, spawn.Percent);
                }
            }
            tg.setTeamFormation(this.TFormation);
            tg.setStartPath(scene, this.StartPointName, this.StartPathHoldMinTimeMS, this.StartPathHoldMaxTimeMS, this.PeaceTime);
            tg.setStartDirection(this.StartDirection);
            tg.setResetOnWithoutAlive(this.ResetOnWithoutAlive);

			//foreach (BindEvent eventItem in this.Events)
			//{
			//	tg.addItemEvent(eventItem.EventName);
			//}

			return tg;
        }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutList<SpawnUnit>(this.UnitTemplates, output.PutExt);
            output.PutList<int>(this.UnitTemplatesID, output.PutS32);
            output.PutS32(this.UnitLevel);
            output.PutS32(this.StartTimeDelayMS);
            output.PutS32(this.IntervalMS);
            output.PutS32(this.OnceCount);
            output.PutS32(this.TotalLimit);
            output.PutS32(this.AliveLimit);
            output.PutBool(this.WithoutAlive);
            output.PutU8(this.Force);
            output.PutUTF(this.UnitName);
            output.PutUTF(this.UnitTag);
            output.PutUTF(this.StartPointName);
            output.PutS32(this.StartPathHoldMinTimeMS);
            output.PutS32(this.StartPathHoldMaxTimeMS);
            output.PutF32(this.StartDirection);
            output.PutExt(this.SpawnEffect);
            output.PutExt(this.TFormation);
            output.PutBool(this.ResetOnWithoutAlive);
			output.PutU8(this.forceMin);
			output.PutU8(this.forceMax);
			output.PutS32(this.PeaceTime);
			//output.PutList<BindEvent>(this.Events, output.PutExt);
		}
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.UnitTemplates = input.GetList<SpawnUnit>(input.GetExt<SpawnUnit>);
            this.UnitTemplatesID = input.GetList<int>(input.GetS32);
            this.UnitLevel = input.GetS32();
            this.StartTimeDelayMS = input.GetS32();
            this.IntervalMS = input.GetS32();
            this.OnceCount = input.GetS32();
            this.TotalLimit = input.GetS32();
            this.AliveLimit = input.GetS32();
            this.WithoutAlive = input.GetBool();
            this.Force = input.GetU8();
            this.UnitName = input.GetUTF();
            this.UnitTag = input.GetUTF();
            this.StartPointName = input.GetUTF();
            this.StartPathHoldMinTimeMS = input.GetS32();
            this.StartPathHoldMaxTimeMS = input.GetS32();
            this.StartDirection = input.GetF32();
            this.SpawnEffect = input.GetExt<LaunchEffect>();
            this.TFormation = input.GetExt<TeamFormation>();
            this.ResetOnWithoutAlive = input.GetBool();
			this.forceMin = input.GetU8();
			this.forceMax = input.GetU8();
			this.PeaceTime = input.GetS32();
			//this.Events = input.GetList<BindEvent>(input.GetExt<BindEvent>);
		}
    }

    [MessageType(0x4404)]
    [DescAttribute("传送点功能")]
    public class UnitTransportAbilityData : RegionAbilityData
    {
        [SceneObjectIDAttribute(typeof(SceneObjectData))]
        [DescAttribute("传送到路点位置")]
        public string NextPosition;

        [DescAttribute("接受的单位类型", "过滤")]
        public UnitInfo.UnitType AcceptUnitType = UnitInfo.UnitType.TYPE_PLAYER;
        [DescAttribute("接受所有类型的单位,此处为True,AcceptUnitType失效", "过滤")]
        public bool AcceptUnitTypeForAll = false;

        [DescAttribute("接受的阵营", "过滤")]
        public byte AcceptForce = 0;
        [DescAttribute("接受所有阵营的单位,此处为True,AcceptForce失效", "过滤")]
        public bool AcceptForceForAll = false;

        [DescAttribute("传送时的特效", "资源")]
        public LaunchEffect TransportEffect;

        public override string ToString()
        {
            return "传送到->" + NextPosition;
        }

        public TransportUnitTrigger CreateTrigger(EditorScene scene)
        {
            TransportUnitTrigger tg = new TransportUnitTrigger(scene, this.Name);
            tg.NextPositionName = this.NextPosition;
            tg.AcceptUnitType = this.AcceptUnitType;
            tg.AcceptUnitTypeForAll = this.AcceptUnitTypeForAll;
            tg.AcceptForce = this.AcceptForce;
            tg.AcceptForceForAll = this.AcceptForceForAll;
            tg.TransportEffect = this.TransportEffect;
            return tg;
        }
        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutUTF(this.NextPosition);
            output.PutU8((byte)this.AcceptUnitType);
            output.PutBool(this.AcceptUnitTypeForAll);
            output.PutU8(this.AcceptForce);
            output.PutBool(this.AcceptForceForAll);
            output.PutExt(this.TransportEffect);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.NextPosition = input.GetUTF();
            this.AcceptUnitType = (UnitInfo.UnitType)input.GetU8();
            this.AcceptUnitTypeForAll = input.GetBool();
            this.AcceptForce = input.GetU8();
            this.AcceptForceForAll = input.GetBool();
            this.TransportEffect = input.GetExt<LaunchEffect>();
        }
    }

    [MessageType(0x4405)]
    [DescAttribute("跨场景传送点功能")]
    public class SceneTransportAbilityData : RegionAbilityData
    {
        [TemplateIDAttribute(typeof(SceneData))]
        [DescAttribute("下一个场景ID")]
        public int NextSceneID;
        [DescAttribute("下一个场景路点位置")]
        public string NextScenePosition;
        [DescAttribute("传送时的特效", "资源")]
        public LaunchEffect TransportEffect;

        public override string ToString()
        {
            return "传送到->场景2:" + NextSceneID+"位置:"+NextScenePosition;
        }
        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(this.NextSceneID);
            output.PutUTF(this.NextScenePosition);
            output.PutExt(this.TransportEffect);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.NextSceneID = input.GetS32();
            this.NextScenePosition = input.GetUTF();
            this.TransportEffect = input.GetExt<LaunchEffect>();
        }
    }

    [MessageType(0x4406)]
    [DescAttribute("物品刷新点")]
    public class SpawnItemAbilityData : RegionAbilityData
    {
        [MessageType(0x4407)]
        [DescAttribute("物品刷新ID")]
        public class SpawnItem : IExternalizable
        {
            [DescAttribute("物品模板")]
            [TemplateIDAttribute(typeof(ItemTemplate))]
            public int ItemTemplateID;
            [DescAttribute("此物品每次刷新概率百分比")]
            public float Percent = 100f;
            public override string ToString()
            {
                return ItemTemplateID.ToString();
            }
            public void WriteExternal(IOutputStream output)
            {
                output.PutS32(ItemTemplateID);
                output.PutF32(Percent);
            }
            public void ReadExternal(IInputStream input)
            {
                this.ItemTemplateID = input.GetS32();
                this.Percent = input.GetF32();
            }
        }
        [DescAttribute("物品类型模板ID和等级组", "基础")]
        public List<SpawnItem> ItemTemplates = new List<SpawnItem>();

        [DescAttribute("延迟启动时间(毫秒)", "可选")]
        public int StartTimeDelayMS;
        [DescAttribute("刷新间隔时间(毫秒)", "基础")]
        public int IntervalMS = 5000;
        [DescAttribute("一次刷新数量", "基础")]
        public int OnceCount = 5;
        [DescAttribute("总刷新数量上限(0表示无上限)", "可选")]
        public int TotalLimit;
        [DescAttribute("存活数量上限(0表示无上限)", "可选")]
        public int AliveLimit;
        [DescAttribute("每次刷新必须所有物品消亡", "基础")]
        public bool WithoutAlive;
        [DescAttribute("物品初始阵营", "基础")]
        public byte Force;
        [DescAttribute("物品初始标记", "可选")]
        public string UnitTag;
        [DescAttribute("物品名字", "可选")]
        public string UnitName;

        [DescAttribute("物品产生时触发的特效", "资源")]
        public LaunchEffect SpawnEffect;

        [DescAttribute("初始朝向(大于等于0有效)", "可选")]
        public float StartDirection = -1;

        public override string ToString()
        {
            return "物品刷新点: " + ItemTemplates.Count + "种类型";
        }

        public SpawnItemTrigger CreateTrigger(EditorScene scene)
        {
            SpawnItemTrigger tg = new SpawnItemTrigger(scene, this.Name);
            tg.setDelayTime(this.StartTimeDelayMS);
            tg.setSpawnInterval(this.IntervalMS);
            tg.setSpawnCount(this.OnceCount);
            tg.setSpawnEffect(this.SpawnEffect);
            tg.setLimitedAliveCount(this.AliveLimit);
            tg.setLimitedSpawnCount(this.TotalLimit);
            tg.setSpawnWithoutAlive(this.WithoutAlive);
            tg.setUnitTag(this.UnitTag);
            tg.setUnitName(this.UnitName);
            tg.setUnitForce(this.Force);
            tg.setStartDirection(this.StartDirection);
            if (ItemTemplates != null)
            {
                foreach (SpawnItem spawn in this.ItemTemplates)
                {
                    tg.addItemInfo(spawn.ItemTemplateID, spawn.Percent);
                }
            }
            return tg;
        }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutList<SpawnItem>(this.ItemTemplates, output.PutExt);
            output.PutS32(this.StartTimeDelayMS);
            output.PutS32(this.IntervalMS);
            output.PutS32(this.OnceCount);
            output.PutS32(this.TotalLimit);
            output.PutS32(this.AliveLimit);
            output.PutBool(this.WithoutAlive);
            output.PutU8(this.Force);
            output.PutUTF(this.UnitName);
            output.PutUTF(this.UnitTag);
            output.PutExt(this.SpawnEffect);
            output.PutF32(this.StartDirection);
		}
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.ItemTemplates = input.GetList<SpawnItem>(input.GetExt<SpawnItem>);
            this.StartTimeDelayMS = input.GetS32();
            this.IntervalMS = input.GetS32();
            this.OnceCount = input.GetS32();
            this.TotalLimit = input.GetS32();
            this.AliveLimit = input.GetS32();
            this.WithoutAlive = input.GetBool();
            this.Force = input.GetU8();
            this.UnitName = input.GetUTF();
            this.UnitTag = input.GetUTF();
            this.SpawnEffect = input.GetExt<LaunchEffect>();
            this.StartDirection = input.GetF32();			
		}
    }

	[MessageType(0x8801)]
	[DescAttribute("玩家复活点")]
	public class XmdsRebirthAbility : RegionAbilityData
	{
		[DescAttribute("阵营")]
		public int START_Force;

		public override string ToString()
		{
			return "玩家复活点: " + START_Force;
		}

		public override void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);
			output.PutS32(START_Force);

		}
		public override void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
			this.START_Force = input.GetS32();
		}
	}

	[MessageType(0x4408)]
	[DescAttribute("区域伤害")]
	public class RegionDamageAbilityData : RegionAbilityData
	{
		[DescAttribute("针对阵营")]
		public int force = 2;

		[DescAttribute("触发间隔")]
		public int interval = 1000;

		[DescAttribute("固定伤害值(负加血)", "动作")]
		public int attack;

		[DescAttribute("固定伤害值百分比(负加血)", "动作")]
		public int attackPer;

		[DescAttribute("产生Buff", "动作")]
		public LaunchBuff DoBuff;

		public override string ToString()
		{
			return "区域伤害: " + force + ", 间隔:" + interval;
		}

		public override void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);
			output.PutS32(force);
			output.PutS32(interval);
			output.PutS32(attack);
			output.PutExt(DoBuff);
			output.PutS32(attackPer);
		}
		public override void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
			this.force = input.GetS32();
			this.interval = input.GetS32();
			this.attack = input.GetS32();
			this.DoBuff = input.GetExt<LaunchBuff>();
			this.attackPer = input.GetS32();
		}


		public RegionDamageTrigger CreateTrigger(EditorScene scene)
		{
			RegionDamageTrigger tg = new RegionDamageTrigger(scene, this);
			return tg;
		}

	}
}