using CommonAI.RTS;
using CommonLang.Vector;
using CommonAI.Zone.Attributes;
using CommonAI.Zone.Instance;
using CommonLang.Property;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonAI.Zone.EventTrigger;

namespace CommonAI.Zone.ZoneEditor.EventTrigger
{
    //--------------------------------------------------------------------------------
    #region __强制动作__

    [DescAttribute("强制动作", "单位 - 剧情/强制动作")]
    public abstract class ForceUnitAction : AbstractAction
    {
        public abstract string ToActionString();
    }

    [DescAttribute("单位待机", "单位 - 剧情/强制动作")]
    public class ForceUnitIdleAction : ForceUnitAction
    {
        [DescAttribute("单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("待机时间")]
        public RealValue TimeSEC = new RealValue.VALUE();

        public override string ToString()
        {
            return string.Format("强制动作({0})待机{1}秒", Unit, TimeSEC);
        }
        public override string ToActionString()
        {
            return string.Format("待机{0}秒", TimeSEC);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            InstanceUnit unit = Unit.GetValue(api, args) as InstanceUnit;
            if (unit != null)
            {
                unit.queueCurrentState(new CommonAI.Zone.Instance.InstanceUnit.ForceStateIdleTime(unit, TimeSEC.GetValue(api, args)));
            }
        }
    }

    [DescAttribute("单位做动作", "单位 - 剧情/强制动作")]
    public class ForceUnitDoAction : ForceUnitAction
    {
        [DescAttribute("单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("动作名字")]
        public string ActionName;

        [DescAttribute("动作持续时间(秒)")]
        public RealValue TimeSEC = new RealValue.VALUE();

        public override string ToString()
        {
            return string.Format("强制动作({0})做动作{1}", Unit, ActionName);
        }
        public override string ToActionString()
        {
            return string.Format("做动作{0}", ActionName);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            InstanceUnit unit = Unit.GetValue(api, args) as InstanceUnit;
            if (unit != null)
            {
                unit.queueCurrentState(new CommonAI.Zone.Instance.InstanceUnit.ForceStateActionTime(unit, TimeSEC.GetValue(api, args), ActionName));
            }
        }
    }

    [DescAttribute("单位移动", "单位 - 剧情/强制动作")]
    public class ForceUnitMoveAction : ForceUnitAction
    {
        [DescAttribute("单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("位置")]
        public PositionValue Pos = new PositionValue.VALUE();

        public override string ToString()
        {
            return string.Format("强制动作({0})移动到{1}", Unit, Pos);
        }
        public override string ToActionString()
        {
            return string.Format("移动到{0}", Pos);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            InstanceUnit unit = Unit.GetValue(api, args) as InstanceUnit;
            Vector2 pos = Pos.GetValue(api, args);
            if (unit != null && pos != null)
            {
                unit.queueCurrentState(new CommonAI.Zone.Instance.InstanceUnit.ForceStateMoveTo(unit, pos.X, pos.Y));
            }
        }
    }

    [DescAttribute("单位改变朝向", "单位 - 剧情/强制动作")]
    public class ForceUnitFaceToAction : ForceUnitAction
    {
        [DescAttribute("单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("方向")]
        public RealValue Direction = new RealValue.VALUE();

        public override string ToString()
        {
            return string.Format("强制动作({0})转向到{1}", Unit, Direction);
        }
        public override string ToActionString()
        {
            return string.Format("转向到{0}", Direction);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            InstanceUnit unit = Unit.GetValue(api, args) as InstanceUnit;
            if (unit != null)
            {
                unit.faceTo(Direction.GetValue(api, args));
            }
        }
    }

    [DescAttribute("单位释放技能", "单位 - 剧情/强制动作")]
    public class ForceUnitLaunchSkillAction : ForceUnitAction
    {
        [DescAttribute("单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("随机技能,如果为True,则SkillTemplateID无效")]
        public BooleanValue RandomSkill = new BooleanValue.VALUE();

        [TemplateIDAttribute(typeof(SkillTemplate))]
        [DescAttribute("技能模板ID")]
        public int SkillTemplateID;

        public override string ToString()
        {
            return string.Format("强制动作({0})释放技能{1}", Unit, SkillTemplateID);
        }
        public override string ToActionString()
        {
            return string.Format("释放技能{0}", SkillTemplateID);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            InstanceUnit unit = Unit.GetValue(api, args) as InstanceUnit;
            if (unit != null)
            {
                unit.queueCurrentState(new CommonAI.Zone.Instance.InstanceUnit.ForceStateLaunchSkill(unit, SkillTemplateID, RandomSkill.GetValue(api, args)));
            }
        }
    }


    [DescAttribute("一系列动作", "单位 - 剧情/强制动作")]
    public class ForceUnitControlQueue : AbstractAction
    {
        [DescAttribute("单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("动作序列")]
        [ListAttribute(typeof(ForceUnitAction))]
        public List<ForceUnitAction> Actions = new List<ForceUnitAction>();

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            foreach (ForceUnitAction act in Actions)
            {
                sb.Append(act.ToActionString() + " -> ");
            }
            sb.Append("END");
            return string.Format("({0})执行序列: {1}", Unit, sb);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            InstanceUnit unit = Unit.GetValue(api, args) as InstanceUnit;
            if (unit != null && Actions.Count > 0)
            {
                new ActionQueueExecuter(api, args, unit, Actions).doNextAction();
            }
        }

        class ActionQueueExecuter
        {
            private EventTriggerAdapter api;
            private EventArguments args;
            private InstanceUnit unit;
            private Queue<ForceUnitAction> actions;

            public ActionQueueExecuter(EventTriggerAdapter api, EventArguments args, InstanceUnit manual, List<ForceUnitAction> actions)
            {
                this.api = api;
                this.args = args;
                this.unit = manual;
                this.actions = new Queue<ForceUnitAction>(actions);
            }

            public void doNextAction()
            {
                if (actions.Count > 0)
                {
                    ForceUnitAction act = actions.Dequeue();
                    if (act is ForceUnitIdleAction)
                    {
                        doIdle(act as ForceUnitIdleAction);
                    }
                    else if (act is ForceUnitMoveAction)
                    {
                        doMove(act as ForceUnitMoveAction);
                    }
                    else if (act is ForceUnitFaceToAction)
                    {
                        doFaceTo(act as ForceUnitFaceToAction);
                    }
                    else if (act is ForceUnitLaunchSkillAction)
                    {
                        doLaunchSkill(act as ForceUnitLaunchSkillAction);
                    }
                    else if (act is ForceUnitDoAction)
                    {
                        doClientAction(act as ForceUnitDoAction);
                    }
                }
            }

            private void doIdle(ForceUnitIdleAction idle)
            {
                InstanceUnit.State state = new InstanceUnit.ForceStateIdleTime(unit, idle.TimeSEC.GetValue(api, args));
                state.AddStopOnce((InstanceUnit u, InstanceUnit.State os) =>
               {
                   doNextAction();
               });
                unit.queueCurrentState(state);
            }

            private void doMove(ForceUnitMoveAction move)
            {
                Vector2 pos = move.Pos.GetValue(api, args);
                if (pos != null)
                {
                    InstanceUnit.State state = new InstanceUnit.ForceStateMoveTo(unit, pos.X, pos.Y);
                    state.AddStopOnce((InstanceUnit u, InstanceUnit.State os) =>
                   {
                       doNextAction();
                   });
                    unit.queueCurrentState(state);
                }
                else
                {
                    doNextAction();
                }
            }

            private void doFaceTo(ForceUnitFaceToAction faceTo)
            {
                unit.faceTo(faceTo.Direction.GetValue(api, args));
                doNextAction();
            }

            private void doLaunchSkill(ForceUnitLaunchSkillAction skill)
            {
                InstanceUnit.State state = new InstanceUnit.ForceStateLaunchSkill(
                    unit,
                    skill.SkillTemplateID,
                    skill.RandomSkill.GetValue(api, args),
                    (InstanceUnit u, InstanceUnit.State os) =>
                {
                    doNextAction();
                });
                unit.queueCurrentState(state);
            }

            private void doClientAction(ForceUnitDoAction skill)
            {
                InstanceUnit.State state = new InstanceUnit.ForceStateActionTime(unit, skill.TimeSEC.GetValue(api, args), skill.ActionName);
                state.AddStopOnce((InstanceUnit u, InstanceUnit.State os) =>
               {
                   doNextAction();
               });
                unit.queueCurrentState(state);
            }

        }

    }

    #endregion

    //--------------------------------------------------------------------------------
    #region __AI__


    [DescAttribute("设置NPC警戒位置", "NPC单位 - AI")]
    public class NpcSetGuardPosition : AbstractAction
    {
        [DescAttribute("NPC单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("警戒位置")]
        public PositionValue Pos = new PositionValue.VALUE();

        public override string ToString()
        {
            return string.Format("设置NPC:{0}警戒在{1}", Unit, Pos);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            IGuardUnit unit = Unit.GetValue(api, args) as IGuardUnit;
            Vector2 pos = Pos.GetValue(api, args);
            if (unit != null && pos != null)
            {
                unit.SetOrginPosition(pos.X, pos.Y);
            }
        }
    }

    [DescAttribute("NPC向路点进发", "NPC单位 - AI")]
    public class NpcAttackToWayPoint : AbstractAction
    {
        [DescAttribute("NPC单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("路点入口")]
        public FlagValue.EditorPoint WayPoint = new FlagValue.EditorPoint();

        public override string ToString()
        {
            return string.Format("NPC:{0}向{1}进发", Unit, WayPoint);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            IGuardUnit unit = Unit.GetValue(api, args) as IGuardUnit;
            ZoneWayPoint pos = WayPoint.GetValue(api, args) as ZoneWayPoint;
            if (unit != null && pos != null)
            {
                unit.AttackTo(pos);
            }
        }
    }
    [DescAttribute("NPC巡逻", "NPC单位 - AI")]
    public class NpcPatrolWithWayPoint : AbstractAction
    {
        [DescAttribute("NPC单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("路点入口")]
        public FlagValue.EditorPoint WayPoint = new FlagValue.EditorPoint();

        [DescAttribute("切换路点待机最小时间(秒)")]
        public RealValue HoldMinTimeSEC = new RealValue.VALUE(0);
        [DescAttribute("切换路点待机最大时间(秒)")]
        public RealValue HoldMaxTimeSEC = new RealValue.VALUE(0);

        public override string ToString()
        {
            return string.Format("NPC:{0}在{1}巡逻", Unit, WayPoint);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            IGuardUnit unit = Unit.GetValue(api, args) as IGuardUnit;
            ZoneWayPoint pos = WayPoint.GetValue(api, args) as ZoneWayPoint;
            if (unit != null && pos != null)
            {
                int holdMinTimeMS = (int)(HoldMinTimeSEC.GetValue(api, args) * 1000);
                int holdMaxTimeMS = (int)(HoldMaxTimeSEC.GetValue(api, args) * 1000);
                unit.PatrolWith(pos, holdMinTimeMS, holdMaxTimeMS);
            }
        }
    }


    [DescAttribute("NPC跟随并警戒", "NPC单位 - AI")]
    public class NpcFollowAndGuardUnit : AbstractAction
    {
        [DescAttribute("NPC单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("跟随的单位")]
        public UnitValue VIP = new UnitValue.Editor();

        public override string ToString()
        {
            return string.Format("NPC:{0}跟随{1}", Unit, VIP);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            IGuardUnit unit = Unit.GetValue(api, args) as IGuardUnit;
            InstanceUnit vip = VIP.GetValue(api, args);
            if (unit != null && vip != null)
            {
                unit.GuardUnit(vip);
            }
        }
    }

    [DescAttribute("NPC追踪并战斗", "NPC单位 - AI")]
    public class NpcFollowAndAttackUnit : AbstractAction
    {
        [DescAttribute("NPC单位")]
        public UnitValue Unit = new UnitValue.Trigging();

        [DescAttribute("目标单位")]
        public UnitValue Target = new UnitValue.Editor();

        [DescAttribute("攻击原因")]
        public Helper.AttackReason Reason = Helper.AttackReason.Tracing;

        public override string ToString()
        {
            return string.Format("NPC:{0}攻击{1}", Unit, Target);
        }
        override public void DoAction(EventTriggerAdapter api, EventArguments args)
        {
            IGuardUnit unit = Unit.GetValue(api, args) as IGuardUnit;
            InstanceUnit target = Target.GetValue(api, args);
            if (unit != null && target != null)
            {
                unit.FollowAndAttack(target, Reason);
            }
        }
    }

    #endregion
}