using CommonAI.Zone;
using CommonAI.Zone.Helper;
using CommonAI.Zone.Instance;
using CommonLang;
using XmdsCommon.Plugin;
using CommonLang.Vector;
using XmdsCommonServer.Plugin.Scene;
using System.Collections.Generic;
using System;
using CommonAI.Zone.Formula;
using static XmdsCommonServer.Plugin.XmdsVirtual;
using static CommonAI.Zone.AttackProp;
using XmdsCommon.Message;
using CommonAI.Data;
using CommonAI;

namespace XmdsCommonServer.Plugin.Units
{
    public class XmdsInstanceMonster : InstanceGuard
    {
        /// <summary>
        /// 储存真正的单位ID.
        /// </summary>
        private int mMonsterID = 0;

        /// <summary>
        /// 获取怪物真正的ID.
        /// </summary>
        /// <returns></returns>
        public int MonsterID
        {
            set { mMonsterID = value; }
            get { return mMonsterID; }
        }

        private float mGuardRangeLimit;
        private float mGuardRange;

        private TimeExpire<int> mIdleMoveHoldTime;
        private WanderConfig mWanderConfig = null;

        public XmdsInstanceMonster(InstanceZone zone, UnitInfo info, string name, int force, int level)
            : base(zone, info, name, force, level)
        {
            mGuardRangeLimit = info.GuardRangeLimit;
            mGuardRange = info.GuardRange;

            if (((zone as XmdsServerScene).Data != null))
            {
                XmdsServerSceneData data = ((zone as XmdsServerScene).Data.Properties as XmdsSceneProperties).ServerSceneData;

                //只有野外地图生效.
                if (data.SceneHard == XmdsServerSceneData.NORMAL_MAP)
                {
                    mWanderConfig = (info.Properties as XmdsUnitProperties).WanderConfigData;

                    if (mWanderConfig == null)
                    {
                        //编辑器未配置时走默认.
                        mWanderConfig = new WanderConfig();
                        mWanderConfig.MaxHoldTimeMS = XmdsConfig.Instance.MAX_HOLD_TIMEMS;
                        mWanderConfig.MinHoldTimeMS = XmdsConfig.Instance.MIN_HOLD_TIMEMS;
                        mWanderConfig.MaxMoveTimeMS = XmdsConfig.Instance.MAX_MOVE_TIMEMS;
                        mWanderConfig.MinMoveTimeMS = XmdsConfig.Instance.MIN_MOVE_TIMEMS;
                        mWanderConfig.WanderRange = XmdsConfig.Instance.WANDE_RRANGE;
                    }

                    if (mWanderConfig.MaxHoldTimeMS > 0)
                    {
                        mIdleMoveHoldTime =
                            new TimeExpire<int>(Parent.RandomN.Next(mWanderConfig.MinHoldTimeMS, mWanderConfig.MaxHoldTimeMS));
                    }
                }
            }

        }

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

		public HateSystem getHateSystem()
		{
			return this.mHateSystem;
		}

        protected override void OnBackToOrgin()
        {
            //DoUnitStateReset();

            base.OnBackToOrgin();
        }

        public void AddEnemy(InstanceUnit target)
        {
            base.onAddEnemy(target, false, AttackReason.Look);
        }

        public override void doSomething()
        {
            base.doSomething();
        }

		public override bool IsMonster { get { return true; } }

		protected override void updateBackToOrgin()
        {
            if (mBackToPosition != null)
            {
                if (mBackToPosition.IsDone)
                {
                    mBackToPosition = null;
                }
            }
            if (mGuardRangeLimit > mGuardRange)
            {
				//if (mCheckInGuardLimit.Update(Parent.UpdateIntervalMS))
				if (mNextCheckGuardLimit != null && mNextCheckGuardLimit.IsTrigger())
				{
					//怪物会原地警戒
					float mGuardRangeLimitTemp = mGuardRangeLimit + 1.5f;

					if (!CMath.includeRoundPoint(X, Y, mGuardRangeLimitTemp, mOrginPosition.X, mOrginPosition.Y))
                    {
                        mHateSystem.forceRemoveAtkTraget();
                        //Console.WriteLine(" - - backToOrgin - 1 " + this.Info.Name);
                        //在自己的攻击范围内,找仇恨,目标
                        if(mHateSystem.updateHateList(mGuardRangeLimit, mOrginPosition) <= 0)
                        {
                            backToOrgin();
                        }
                        else
                        {
                            //boss寻找下一个攻击目标
                            mTracingTarget = null;
                            InstanceUnit unit = mHateSystem.GetHated();
                            if (unit is InstancePlayer)
                            {

                            }
                            followAndAttack(mHateSystem.GetHated(), AttackReason.Look);
                        }

                        //mHateSystem.print();
                    }
                    else if (mTracingTarget != null)
                    {
                        if (!mTracingTarget.IsActive || !CMath.intersectRound(
                            X, Y, mGuardRangeLimit,
                            mTracingTarget.TargetUnit.X,
                            mTracingTarget.TargetUnit.Y,
                            mTracingTarget.TargetUnit.BodyHitSize))
                        {
                            //Console.WriteLine(" - - backToOrgin - 2 " + this.Info.Name);

                            mHateSystem.Remove(mTracingTarget.TargetUnit);
                            if(mHateSystem.getHateSize() <= 0)
                            {
                               backToOrgin();
                            }else
                            {
                                //boss寻找下一个攻击目标
                                mTracingTarget = null;
                                followAndAttack(mHateSystem.GetHated(), AttackReason.Look);
                            }
                           
                            return;
                        }
                    }
                }
            }
        }

        protected virtual void updateIdle()
        {
            //不能移动单位,也不游荡
            if (CurrentActionStatus == UnitActionStatus.Idle && this.Moveable && 
                (this.Virtual as XmdsVirtual).CombatState == BattleStatus.None)
            {
                if (mIdleMoveHoldTime != null && mIdleMoveHoldTime.Update(Parent.UpdateIntervalMS))
                {
                    //发呆时间.
                    mIdleMoveHoldTime.Reset(Parent.RandomN.Next(mWanderConfig.MinHoldTimeMS, mWanderConfig.MaxHoldTimeMS));
                    //游荡时间、游荡范围.
                    idleMove(Parent.RandomN.Next(mWanderConfig.MinMoveTimeMS, mWanderConfig.MaxMoveTimeMS), mWanderConfig.WanderRange);
                }
            }
        }

        public override void guardInPosition(Vector2 pos)
        {
            if (this.IsDead() == false)
            {
                DoUnitStateReset();
            }

            if (CurrentState is StateIdleMove && pos == mOrginPosition)
            {
                // 浪切换到发呆,别回原点 //
                base.guardInPosition(new Vector2(X, Y));
            }
            else
            {
                base.guardInPosition(pos);
            }

        }

        //怪物返回原点时,状态重置.
        private void DoUnitStateReset()
        {
            var v = this.Virtual as XmdsVirtual_Monster;

            if (v != null)
            {
                v.DoUnitStateReset();
            }
        }

        public void SetGuardRange(float r)
        {
            if (mViewTrigger is ViewTriggerRoundBody)
            {
                mGuardRange = r;
                (mViewTrigger as ViewTriggerRoundBody).SetLookRange(r);
            }
        }

        protected override void onNewStateBeginChange(State old_state, ref State new_state)
        {
            if (new_state is StateBackToPosition)
            {
                if(this.Info.Attributes != null && this.Info.Attributes.Length > 0)
                {
                    //特殊的怪物不回血, 如要特殊处理,初始化就弄
                   // String par = this.Info.Attributes[0];
                   // if (par.Equals("noRecover"))
                    {
                        this.clearBuffs();
                    }
                }
                else
                {
                    //回血.
                    this.AddHP(this.MaxHP, null);
                    this.AddMP(this.MaxMP, null);
					this.Virtual.StartRecoverMP(true);
                    //去BUFF.
                    this.clearBuffs();
                }
                

            }

            base.onNewStateBeginChange(old_state, ref new_state);
        }

        public override BuffState AddBuff(BuffTemplate buff, InstanceUnit sender, int pointMaxOverLayer = 0, bool forever = false, bool bMaxOverlayer = false,
			int buffExt = 0, bool isControlBuf = false, bool bMaxRest = false, int addLayers = 0)
        {
			if (!buff.forceAdd && this.Virtual.IsBoss() && XmdsInstanceUtils.IsControlBuff_Monster(buff))//BOSS不吃控制
			{
				return null;
			}

			return base.AddBuff(buff, sender, pointMaxOverLayer, forever, bMaxOverlayer, buffExt, isControlBuf, bMaxRest, addLayers);
        }
        public override void InitSkills(LaunchSkill baseSkill, params LaunchSkill[] skills)
        {
            if (this.Virtual == null ||
               (this.Virtual as XmdsVirtual).IsFinishSkillInit() == false)
            {
                return;
            }


            base.InitSkills(baseSkill, skills);
        }

        protected SkillState GetAvailableSkillExceptDefaultSkill()
        {
            SkillState ret = null;

            List<SkillState> list = SkillStatus as List<SkillState>;

            for (int si = list.Count - 1; si >= 0; --si)
            {
                SkillState sst = list[si];

                if (DefaultSkill != null && sst.Data.ID != DefaultSkill.ID)
                {
                    if (!sst.IsCD && sst.IsActive && sst.IsDone)
                    {
                        ret = sst;
                        break;
                    }
                }
            }

            return ret;
        }

        public override void guard()
        {
            if (IsNoneSkill)
            {
                mTracingTarget = null;
                base.startIdle();
                return;
            }

            if (this.Info.GuardRange > 0)
            {
                InstanceUnit min = null;
                float min_len = float.MaxValue;
                bool isSpecial = false;
                float guardRangSqua = mGuardRange * mGuardRange;
                Parent.ForEachNearObjects(this.X, this.Y, this.Info.GuardRange, (InstanceUnit u, ref bool cancel) =>
                {
                    float len = MathVector.getDistanceSquare(u.X, u.Y, this.X, this.Y);
                    if (len > guardRangSqua)
                    {
                        return;
                    }

                    if (!Parent.IsAttackable(this, u, SkillTemplate.CastTarget.Enemy, AttackReason.Look, Info))
                    {
                        return;
                    }

                    if (u.Info.Properties is XmdsUnitProperties prop && prop.GameStatusType > XmdsUnitProperties.StatusType.Normal)
                    {
                        if (isSpecial)
                        {
                            if (len < min_len)
                            {
                                min = u;
                                min_len = len;
                            }
                        }
                        else
                        {
                            min = u;
                            min_len = len;
                            isSpecial = true;
                        }
                    }
                    else if (!isSpecial && min_len > len)
                    {
                        min_len = len;
                        min = u;
                    }
                });

                if (min != null)
                {
                    changeState(new StateFollowAndAttack(this, min, SkillTemplate.CastTarget.Enemy));
                    return;
                }
            }
            
            base.guard();
        }

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

        protected override void onResetAI()
        {
            mTracingTarget = null;
            doSomething();
        }

        protected override void Disposing()
        {
            mIdleMoveHoldTime = null;
            mWanderConfig = null;

            base.Disposing();
        }

        protected override void doHitAttack(InstanceUnit attacker, AttackSource source)
        {
            base.doHitAttack(attacker, source);
            if (IsDead() && source.OutClientState == (int)UnitHitEventState.Crit && this.Weight < XmdsConstConfig.DEFAULT_WEIGHT
				&& source.Attack.killHitMove!=null && source.Attack.killHitMove.enable)
            {
                HitMoveType moveType = source.Attack.killHitMove.moveType;
                changeState(new StateDeadFuckFuck(this, source, attacker, moveType), true);
            }
        }

        protected override void onBack2PositionStart()
        {
            (this.Virtual as XmdsVirtual_Monster).changeRunSpeed4back();
        }

        protected override void onBack2PositionEnd()
        {
            (this.Virtual as XmdsVirtual_Monster).onBack2PositionEnd();
        }

        protected override void onAddEnemy(InstanceUnit target, bool group, AttackReason reason)
        {
            var state = CurrentState;
            InstanceUnit nowTarget = null;
            if (state is StateFollowAndAttack attackstate)
            {
                nowTarget = attackstate.TargetUnit;
            }
            else if(state is StateSkill skillstate)
            {
                nowTarget = skillstate.TargetUnit;
            }

            //当前正在追踪/攻击一个价值更高的目标时,不理会小啰啰的攻击
            if (nowTarget != null && nowTarget.Info.Properties is XmdsUnitProperties prop && prop.GameStatusType > XmdsUnitProperties.StatusType.Normal)
            {
                if(target.Info.Properties is XmdsUnitProperties propnew && propnew.GameStatusType > prop.GameStatusType)
                {
                }
                else
                {
                    return;
                }
            }
            
            base.onAddEnemy(target, group, reason);
        }
    }
}