using CommonAI.RTS;
using CommonLang.Vector;
using CommonAI.Zone.Helper;
using CommonLang;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonAI.Zone.Instance.Helper;
using CommonAI.Data;

namespace CommonAI.Zone.Instance
{
    public class InstancePet : InstanceUnit, ISummonedUnit
    {
        protected InstanceUnit mMaster;
        protected StateFollowMaster mFollowMaster;
        public InstanceUnit Owner { get { return this; } }

        public InstancePet(InstanceZone zone, UnitInfo info, string name, int force, int level)
            : base(zone, info, name, force, level)
        {
			s_mFollowDistance = Templates.CFG.PET_FOLLOW_DISTANCE_MIN + (Templates.CFG.PET_FOLLOW_DISTANCE_MAX - Templates.CFG.PET_FOLLOW_DISTANCE_MIN) / 2;
		}

        public override bool IntersectMap { get { return Info.BodySize > 0; } }
        public override bool IntersectObj { get { return false; } }
        public override bool IsActive { get { return false; } }
        public override bool IsAttackable { get { return false; } }

        /// <summary>
        /// 获取主人
        /// </summary>
        public virtual InstanceUnit Master
        {
            get { return mMaster; }
            set { this.mMaster = value; this.mFollowMaster = new StateFollowMaster(this, mMaster); }
        }
        public virtual InstanceUnit SummonerUnit
        {
            get { return Master; }
            set { Master = value; }
        }

		/// <summary>
		/// IAO标记
		/// </summary>
		public override ObjectAoiStatus AoiStatus { get { return this.Master == null ? base.AoiStatus : this.Master.AoiStatus; } }

		// 跟随最大最小距离的中间值
		public static float s_mFollowDistance = 0;


        protected override void onUpdate(bool slowRefresh)
        {
            base.onUpdate(slowRefresh);

            OnPetUpdate();
        }

        protected virtual void OnPetUpdate()
        {
            if (mMaster != null)
            {
                if (mMaster.IsDead() || !mMaster.Enable)
                {
                    this.kill(this);
                }
                else if (!CMath.includeRoundPoint(X, Y, Templates.CFG.PET_FOLLOW_DISTANCE_LIMIT, mMaster.X, mMaster.Y))
                {
                    this.transportToMaster();
                }
                else if (!CMath.includeRoundPoint(X, Y, Templates.CFG.PET_FOLLOW_DISTANCE_MAX, mMaster.X, mMaster.Y))
                {
                    this.followMaster();
                }
            }
            if (CurrentState is StateIdle)
            {
                doSomething2();
            }
        }

        protected void transportToMaster()
        {
            float dx, dy;
            CMath.RandomPosInRound(Parent.RandomN, mMaster.X, mMaster.Y, Templates.CFG.PET_FOLLOW_DISTANCE_MAX, out dx, out dy);
            if (IntersectMap && Parent.TryTouchMap(this, dx, dy))
            {
                dx = Master.X;
                dy = Master.Y;
            }

			this.Virtual.SetCombatState(BattleStatus.None);
			this.transport(dx, dy);
            this.followMaster();
        }

        protected void followMaster()
        {
            StateSkill skillState = this.CurrentState as StateSkill;
            if (skillState != null && skillState.Skill != null && !skillState.IsCancelableByMove)
            {
                return;
            }
			else if(CurrentState == mFollowMaster)
			{
				return;
			}
			
			//float distanceTemp = MathVector.getDistance(this.X, this.Y, this.Master.X, this.Master.Y);
			float speedChag = 1.01f;// (distanceTemp < s_mFollowDistance) ? 1.01f :  1.1f;
			this.followMasterChangeSpeed(speedChag);
			changeState(mFollowMaster);
			//System.Console.WriteLine("---followMaster: " + TimeUtil.GetTimestampMS() + speedChag);
		}

		protected virtual void followMasterChangeSpeed(float speedChag)
		{
			// 随从使用主人的速度
			if (this.Master != null)
			{
				this.SetMoveSpeed(this.Master.MoveSpeedSEC * speedChag);
			}

		}

		protected void doSomething2()
        {
            if (!IsNoneSkill)
            {
                using (var list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
                {
                    //随机找个目标施法//
                    Parent.getObjectsRoundRange<InstanceUnit>(Collider.Object_Pos_IncludeInRound, X, Y, Info.GuardRange, list, this.AoiStatus);
                    DoAndRemoveCollection.UpdateAndRemove<InstanceUnit>(list, (InstanceUnit u) =>
                    {
                        return !u.IsActive;
                    });
                    CUtils.RandomList(Parent.RandomN, list);
                    foreach (SkillState skill in SkillStatus)
                    {
                        if (skill.LaunchSkill.AutoLaunch && skill.TryLaunch())
                        {
                            foreach (InstanceUnit u in list)
                            {
                                if (Parent.IsAttackable(this, u, skill.Data.ExpectTarget, AttackReason.Look, skill.Data))
                                {
                                    //检测是否有可释放技能//
                                    if (tryAutoLaunch(skill, u))
                                    {
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        protected virtual bool tryAutoLaunch(SkillState st, InstanceUnit target)
        {
            if (st != null && st.LaunchSkill.AutoLaunch)
            {
                changeState(new StateFollowAndAttack(this, target, st.Data.ExpectTarget));
                return true;
            }
            return false;
        }

        protected override void Disposing()
        {
            mMaster = null;
            mFollowMaster = null;
            base.Disposing();
        }


        //----------------------------------------------------------------------------------------------------------
        protected override IUnitStatistic CreateUnitStatistic()
        {
            return new PetUnitStatistic(this);
            //return base.CreateUnitStatistic();
        }
        public class PetUnitStatistic : UnitStatistic
        {
            private InstancePet owner;
            public PetUnitStatistic(InstancePet owner) : base(owner)
            {
                this.owner = owner;
            }
            public override void onAttack(InstanceUnit target, int reduceHP)
            {
                //伤害统计重定向到主人//
                if (owner.Master != null)
                {
                    owner.Master.Statistic.onAttack(target, reduceHP);
                }
                else
                {
                    base.onAttack(target, reduceHP);
                }
            }

            public override void onKill(InstanceUnit target)
            {
                //击杀统计重定向到主人//
                if (owner.Master != null)
                {
                    owner.Master.Statistic.onKill(target);
                }
                else
                {
                    base.onKill(target);
                }
            }
        }
        //----------------------------------------------------------------------------------------------------------
        /// <summary>
        /// 移动状态
        /// </summary>
        public class StateFollowMaster : State
        {
            // 被追目标
            readonly private InstanceZoneObject master;
            private MoveAI move;
            public StateFollowMaster(InstancePet unit, InstanceZoneObject target)
                : base(unit)
            {
                this.master = target;
                this.move = new MoveAI(unit);
            }

            override public bool onBlock(State new_state)
            {
                if (new_state is StateDead)
                {
                    return true;
                }
                if (new_state is StateFollowMaster)
                {
                    return true;
                }
                float r = Math.Max(zone.Templates.CFG.PET_FOLLOW_DISTANCE_MIN, master.BodyBlockSize + unit.BodyBlockSize);
                if (CMath.includeRoundPoint(unit.X, unit.Y, r, master.X, master.Y))
                {
                    unit.SetActionStatus(UnitActionStatus.Idle);
                    return true;
                }

                StateSkill stateSkill = new_state as StateSkill;
                if(stateSkill != null && !stateSkill.IsCancelableByMove)
                {
                    return true;
                }

                return false;
            }
            override protected void onStart()
            {
                unit.SetActionStatus(UnitActionStatus.Move);
                this.move.FindPath(master);
            }

            override protected void onUpdate()
            {
                float r = Math.Max(zone.Templates.CFG.PET_FOLLOW_DISTANCE_MIN, master.BodyBlockSize + unit.BodyBlockSize);
                if (CMath.includeRoundPoint(unit.X, unit.Y, r, master.X, master.Y))
                {
                    unit.SetActionStatus(UnitActionStatus.Idle);
                    unit.doSomething();
                }
                else
                {
                    move.Update();
                    if (move.IsNoWay)
                    {
                        (unit as InstancePet).transportToMaster();
                    }
                }
            }

            override protected void onStop()
            {
                unit.SetActionStatus(UnitActionStatus.Idle);
            }

        }

    }
}