using CommonAI.Data;
using CommonAI.Zone;
using CommonAI.Zone.Helper;
using CommonAI.Zone.Instance;
using CommonLang;
using CommonLang.Geometry;
using CommonLang.Vector;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XmdsCommon.Message;
using XmdsCommon.Plugin;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.DamageCalculator;
using static CommonAI.Zone.SkillTemplate;

namespace XmdsCommonServer.Plugin.Units
{
    public class XmdsInstancePet : InstancePet
    {
		private XmdsCommon.Plugin.XmdsPetConifg.XmdsPetFollowMode mCurFollowMode = XmdsCommon.Plugin.XmdsPetConifg.XmdsPetFollowMode.ActiveAtk;

        //主人当前战斗状态.
        private BattleStatus mMasterCombatStatus;

        private InstanceUnit mCurAtkUnit = null;

		//跟随最大距离的平方
		private float mMaxFollowDistance = 10;

        public XmdsInstancePet(InstanceZone zone, UnitInfo info, string name, int force, int level)
            : base(zone, info, name, force, level)
        {
			this.mMaxFollowDistance = (float)Math.Pow(Templates.CFG.PET_FOLLOW_DISTANCE_MAX, 2);
		}

        public override bool IsActive
        {
            get { return (this.Enable) && (this.CurrentHP > 0) && (MasterIsReady() && !IsMasterDead()); }
        }

        public override bool IsAttackable { get { return (this.Enable && MasterIsReady() && !IsMasterDead()); } }

        public override bool IsVisible
        {
            get
            {
                if (mMaster != null && mMaster.IsDead() == true)
                {
                    return false;
                }

                return base.IsVisible;
            }
        }

        public bool MasterIsReady()
        {
            if (mMaster == null) { return true; }

            else
            {
                if (mMaster is XmdsInstancePlayer)
                {
                    return (mMaster as XmdsInstancePlayer).IsPlayerReady();
                }
            }
            return true;
        }

        private bool IsMasterDead()
        {
            if (mMaster == null) { return false; }
            return mMaster.IsDead();
        }

		protected virtual bool CheckFollowMaster() { return true; }

        protected override void OnPetUpdate()
        {         
            if (mMaster != null && !IsMasterDead() && MasterIsReady())
            {
                if (this.CheckFollowMaster() && !CMath.includeRoundPoint(X, Y, Templates.CFG.PET_FOLLOW_DISTANCE_LIMIT, mMaster.X, mMaster.Y))
                {
                    mCurAtkUnit = null;
                    this.transportToMaster();
                }
                else
                {
                    //if ((this.Virtual as XmdsVirtual).CombatState != BattleStatus.None)
                    //{
                    //    float d = 0;
                    //    //非战斗状态.
                    //    d = Templates.CFG.PET_FOLLOW_DISTANCE_MAX;

                    //    if (!CMath.includeRoundPoint(X, Y, d, mMaster.X, mMaster.Y))
                    //    {
                    //        mCurAtkUnit = null;
                    //        this.followMaster();
                    //    }
                    //}
                }

				//2021.11.1 主人脱战了,并且没有伤害,宠物强行脱战(宠物战斗会导致玩家无法脱战)
				//2020.9.22修改,宠物可以和怪物撕逼
                if (this.checkOutOffBattle())
                {
                    mCurAtkUnit = null;

                    //if ((this.Virtual as XmdsVirtual).CombatState == BattleStatus.None || (this.Virtual as XmdsVirtual).CombatState == BattleStatus.ReadyBattle)
					if(this.CheckFollowMaster() && this.Virtual.GetBattleStatus() <= BattleStatus.ReadyBattle)
                    {
                        float d = 0;
                        //战斗状态.
                        d = Math.Max(XmdsConfig.Instance.PET_IDLE_FOLLOW_MAX_DISTANCE, Master.BodyBlockSize + this.BodyBlockSize);

                        if (!CMath.includeRoundPoint(X, Y, d, mMaster.X, mMaster.Y))
                        {
                            this.followMaster();
                        }
                    }

                    DoSomethingByMode();
                }
                else if (CurrentState is StateFollowAndAttack)
                {
                    mCurAtkUnit = (CurrentState as StateFollowAndAttack).TargetUnit;
                }
            }
			else if(this.Info.SumType == SummonType.attack && CurrentState is StateIdle)
			{
				DoSomethingByMode();
			}
        }

        public virtual bool checkOutOffBattle()
        {
            if (CurrentState is StateIdle || (this.Master.mLastHitOtherTime + XmdsConfig.Instance.OUTOF_BATTLE_PLAYER < CommonLang.CUtils.localTimeMS
                    && this.Master.mLastDamageTime + XmdsConfig.Instance.OUTOF_BATTLE_PLAYER < CommonLang.CUtils.localTimeMS))
            {
                return true;
            }

            return false;
        }

        public void SetFollowMode(XmdsCommon.Plugin.XmdsPetConifg.XmdsPetFollowMode mode)
        {
            if (mCurFollowMode != mode)
            {
                mCurFollowMode = mode;
            }
        }

		// 获取队伍的天命属性加成
		public override int GetTeamFateValue(UnitFateType fateType)
		{
			if(this.Master == null)
			{
				return 0;
			}

			return this.Master.GetTeamFateValue(fateType);
		}

		public void DoSomethingByMode()
        {
            if (IsNoneSkill) { return; }

            //当前模式.
            switch (mCurFollowMode)
            {
                case XmdsCommon.Plugin.XmdsPetConifg.XmdsPetFollowMode.ActiveAtk:
					if (!IsPetCanAttack() && this.Master.CurrentActionStatus == UnitActionStatus.Move && !(this.CurrentState is StateFollowMaster))
					{
						this.Virtual.SetCombatState(BattleStatus.None);
						this.followMaster();
						break;
					}
					else if (mMasterCombatStatus == BattleStatus.PVP)
                    {
                        //优先寻找与主人有PK关联的怪物(IsPlayer).
                        if (TryAtkMasterEnemy(FindEnemy()))
                        {
                            return;
                        }
						else
						{
							TryAtkSelfEnemy();
							return;
						}
					}
                    else
                    {
						if (TryAtkSelfEnemy())
						{
							return;
						}
						else
						{
							TryAtkMasterEnemy(FindEnemy());
							return;
						}						
                    }
                case XmdsCommon.Plugin.XmdsPetConifg.XmdsPetFollowMode.PassiveAtk:
					if (!IsPetCanAttack() && this.Master.CurrentActionStatus == UnitActionStatus.Move && !(this.CurrentState is StateFollowMaster))
					{
						this.Virtual.SetCombatState(BattleStatus.None);
						this.followMaster();
						break;
					}
					else
					if (mMasterCombatStatus == BattleStatus.PVP)
                    {
                        //优先寻找与主人有PK关联的怪物(IsPlayer).
                        if (TryAtkMasterEnemy(FindEnemy()))
                        {
                            return;
                        }
                    }
                    else if (mMasterCombatStatus == BattleStatus.PVE)
                    {
                        if (TryAtkMasterEnemy(FindEnemy()))
                        {
                            return;
                        }
                    }

					//如果没有找到敌人,且自己战斗状态下,攻击自己的敌人
                    if(this.Virtual.GetBattleStatus() > BattleStatus.ReadyBattle)
                    {
						//找不到再寻找自己的敌人.
						if (TryAtkSelfEnemy())
						{
							return;
						}
					}
                    break;
                case XmdsCommon.Plugin.XmdsPetConifg.XmdsPetFollowMode.FollowMaster:
                    //跟随宿主.什么都不做.
                    break;
                default:
                    break;
            }
        }

        public void OnMasterChangeCombatStatus(BattleStatus status)
        {
            mMasterCombatStatus = status;

            //如果变更为PVP模式,宠物立即切换攻击目标.
            if (mMasterCombatStatus == BattleStatus.PVP)
            {
                if (this.CurrentState is StateSkill)
                {
                    var ss = CurrentState as StateSkill;
                    ss.block();
                }

                DoSomethingByMode();
            }
        }

		public override bool IsPet { get { return true; } }
		public override bool IsPlayerUnit { get { return true; } }

		/// <summary>
		/// PVP模式下找出与主人有PVP关联且离自己最近的单位.
		/// 非PVP模式下找出与主人有战斗关联且离自己最近的单位.
		/// </summary>
		/// <param name="ispvp"></param>
		/// <returns></returns>
		private List<HateSystem.HateInfo> FindEnemy()
		{
			var master = this.Master;			
			if (master == null)
			{
				return null;
			}

			var masterVirtual = (master.Virtual as XmdsVirtual);
			if (masterVirtual == null)
			{
				return null;
			}

			var hateSystem = masterVirtual.GetHateSystem();
			//bool pa = false;
			//bool pb = false;

			List<HateSystem.HateInfo> list = new List<HateSystem.HateInfo>();
			hateSystem.GetHateList(list);

			if (list != null && list.Count > 0)
			{
				list.Sort((a, b) =>
				{
					//选距离最近的单位.
					float da = CMath.getDistanceSquare(a.Unit.X, a.Unit.Y, this.X, this.Y);
					float db = CMath.getDistanceSquare(b.Unit.X, b.Unit.Y, this.X, this.Y);
					return (int)(da - db);
				});
				return list;
			}

			return null;				
        }

		/** 是否可攻击 */
		//2021.1.6修改,放弃宠物自行攻击的逻辑,总是被人物束缚,没法攻击自己的敌人
		protected virtual bool IsPetCanAttack()
		{
			var master = this.Master;
			if (master != null)
			{
				if (master.mLastHitOtherTime + XmdsConfig.Instance.OUTOF_BATTLE_PLAYER > CommonLang.CUtils.localTimeMS ||
				master.mLastDamageTime + XmdsConfig.Instance.OUTOF_BATTLE_PLAYER > CommonLang.CUtils.localTimeMS ||
				this.mLastDamageTime + XmdsConfig.Instance.OUTOF_BATTLE_PLAYER > CommonLang.CUtils.localTimeMS)
				{
					return true;
				}
			}

			return false;
		}

        /// <summary>
        /// 攻击主人的敌人(优先PLAYER距离最近).
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        private bool TryAtkMasterEnemy(List<HateSystem.HateInfo> list)
        {
            bool ret = false;

            if (list == null || list.Count == 0) { return ret; }

            foreach (SkillState skill in SkillStatus)
            {
                if (skill.LaunchSkill.AutoLaunch && skill.TryLaunch())
                {
                    if(skill.Data.ExpectTarget == CastTarget.PetForMaster)
                    {
                        //是否在守卫范围内.
                        if (CheckInAtkRange(this.Master, skill.Data.AttackRange))
                        {
                            if (tryAutoLaunch(skill, this.Master))
                            {
                                return true;
                            }
                        }
                    }
                    else 
                    {
                        foreach (HateSystem.HateInfo hi in list)
                        {
                            InstanceUnit u = hi.Unit;

                            if (this.IsCanAttack(hi.Unit) && Parent.IsAttackable(this, u, skill.Data.ExpectTarget, AttackReason.Attack, skill.Data))
                            {
                                //是否在守卫范围内.
                                if (CheckInAtkRange(u, skill.Data.AttackRange))
                                {
                                    //检测是否有可释放技能//
                                    if (tryAutoLaunch(skill, u))
                                    {
                                        return true;
                                    }
                                }
                            }
                        }
                    }
                    
                }
            }

            return ret;
        }

		protected virtual bool IsCanAttack(InstanceUnit unit)
		{
			return unit.IsMonster;
		}

        protected override bool tryAutoLaunch(SkillState st, InstanceUnit target)
        {
            if(st == null)
            {
                return false;
            }

            //var v = (this.Virtual as XmdsVirtual);
           // if (v != null && v.AllowAutoLaunch(st.LaunchSkill.SkillID))
            if(st.LaunchSkill.AutoLaunch && st.TryLaunch())
            {
                changeState(new StateFollowAndAttack(this, target, st.Data.ExpectTarget));
                return true;
            }

            return false;
        }

        /// <summary>
        /// 攻击自身敌人(距离最近).
        /// </summary>
        /// <returns></returns>
        protected virtual bool TryAtkSelfEnemy()
        {
            bool ret = false;

            //using (var list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
            //{
            //    //找到离自己最近的单位攻击.
            //    Parent.getObjectsRoundRange<InstanceUnit>(Collider.Object_BlockBody_TouchRound, X, Y, Info.GuardRange, list , AoiStatus);
            //    DoAndRemoveCollection.UpdateAndRemove<InstanceUnit>(list, (InstanceUnit u) =>
            //    {
            //        return !u.IsActive;
            //    });

            //    if (list != null && list.Count > 0)
            //    {
            //        list.Sort((a, b) =>
            //        {
            //            //选距离最近的单位.
            //            float da = CMath.getDistanceSquare(a.X, a.Y, this.X, this.Y);
            //            float db = CMath.getDistanceSquare(b.X, b.Y, this.X, this.Y);
            //            return (int)(da - db);
            //        });

            //        foreach (SkillState skill in SkillStatus)
            //        {
            //            if (skill.LaunchSkill.AutoLaunch && skill.TryLaunch())
            //            {
            //                foreach (InstanceUnit u in list)
            //                {
            //                    if (this.IsCanAttack(u) && Parent.IsAttackable(this, u, skill.Data.ExpectTarget, AttackReason.Attack, skill.Data))
            //                    {
            //                        //是否在守卫范围内.
            //                        if (CheckInAtkRange(u, this.Info.GuardRange + skill.Data.AttackRange))
            //                        {
            //                            //检测是否有可释放技能//
            //                            if (tryAutoLaunch(skill, u))
            //                            {
            //                                return true;
            //                            }
            //                        }
            //                    }
            //                }
            //            }
            //        }

            //    }
            //}
            return ret;
        }

        public override void InitSkills(LaunchSkill baseSkill, params LaunchSkill[] skills)
        {
            if (this.Virtual == null ||
               (this.Virtual as XmdsVirtual).IsFinishSkillInit() == false)
            {
                return;
            }

            base.InitSkills(baseSkill, skills);
        }
        /// <summary>
        /// 判断该单位是否处在可攻击范围内.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="skillrange"></param>
        /// <returns></returns>
        protected bool CheckInAtkRange(InstanceUnit target, float skillrange)
        {
            bool ret = false;

            //两圆相切.
            var atkr = this.GetSkillAttackRange(skillrange);

			if (Collider.Object_HitBody_TouchRound(target, this.X, this.Y, atkr))
			{
				return true;
			}
			else if (this.SummonerUnit != null && target != null)
            {
				////宠物可以离开宿主的最大范围.
				//float da = (float)Math.Pow(Templates.CFG.PET_FOLLOW_DISTANCE_MAX, 2);

				//CommonLang.Geometry.Vector2 v1 = new CommonLang.Geometry.Vector2(this.X, this.Y);
				//CommonLang.Geometry.Vector2 v2 = new CommonLang.Geometry.Vector2(target.X, target.Y);
				////方向.
				//CommonLang.Geometry.Vector2 dir = (v2 - v1);
				//dir.Normalize();
				//var pos = v2 - dir * (atkr * target.BodyHitSize);
				//float rd = CMath.getDistanceSquare(pos.X, pos.Y, this.SummonerUnit.X, this.SummonerUnit.Y);

				////在范围内.
				//if (rd < da)
				//{
				//    ret = true;
				//}
				ret = CMath.getDistanceSquare(target.X, target.Y, this.SummonerUnit.X, this.SummonerUnit.Y) < this.mMaxFollowDistance;

			}

            return ret;
        }

        public override bool tryLaunchRandomSkillAndCancelCurrentSkill(InstanceUnit target, bool autoFocusNearTarget = false)
        {
            //自动战斗不允许中断当前技能施放.
            return false;
        }

		/** 计算并获得伤害 */
		public override void PetShareDamage(int baseDmgValue, InstanceUnit sender)
		{
			XmdsVirtual petVirtual = this.Virtual as XmdsVirtual;
			int finalDmg = XmdsDamageCalculator.GetPetDamage(baseDmgValue, petVirtual);

			//分发事件
			finalDmg = petVirtual.DispatchShareMasterDmgEvent(finalDmg, sender);
			
			this.AddHP(-finalDmg, sender);
		}

		public override void doSomething()
        {
            if (CurrentState is StateSkill)
            {
                var target = mCurAtkUnit;
                if (target != null)
                {
                    if (tryMoveScatterTarget(target)) { return; }
                }
            }

            base.doSomething();
        }

        /// <summary>
        /// 攻击间歇,尝试换个位置,避免怪物堆在一个点
        /// </summary>
        protected virtual bool tryMoveScatterTarget(InstanceUnit target)
        {
            //只有单位为非碰撞时,才有这个需求//
            if (!this.IntersectObj)
            {
                if (CommonLang.CUtils.localTimeMS > mCheckAttackSpread && CUtils.RandomPercent(Parent.RandomN, Templates.CFG.AI_NPC_ATTACK_IDLE_SCATTER_PCT))
                {
					mCheckAttackSpread = CommonLang.CUtils.localTimeMS + Templates.CFG.AI_NPC_ATTACK_IDLE_INTERVAL;
					InstanceUnit block = null;
                    Parent.ForEachNearObjects(X, Y, (InstanceZoneObject o, ref bool cancel) =>
                    {
                        if ((o != this) && (o is InstanceUnit) && Parent.TouchObject2(this, o))
                        {
                            block = o as InstanceUnit;
                            cancel = true;
                        }
                    });
                    if (block != null)
                    {
                        float degree = MathVector.getDegree(X, Y, target.X, target.Y);
                        float distance = this.BodyBlockSize + block.BodyBlockSize;
                        CommonLang.Vector.Vector2 turnL = new CommonLang.Vector.Vector2(X, Y);
                        CommonLang.Vector.Vector2 turnR = new CommonLang.Vector.Vector2(X, Y);
                        MathVector.movePolar(turnL, degree + CMath.PI_DIV_2, distance);
                        MathVector.movePolar(turnR, degree - CMath.PI_DIV_2, distance);
                        float dl = MathVector.getDistanceSquare(turnL.X, turnL.Y, target.X, target.Y);
                        float dr = MathVector.getDistanceSquare(turnR.X, turnR.Y, target.X, target.Y);
                        if (dl < dr)
                        {
                            this.startMoveTo(turnL.X, turnL.Y);
                        }
                        else
                        {
                            this.startMoveTo(turnR.X, turnR.Y);
                        }
                        return true;
                    }
                }
            }
            return false;
        }

        protected override void Disposing()
        {
            mCurAtkUnit = null;

            base.Disposing();
        }
    }
}