using CommonAI.Zone;
using CommonLang;
using System.Collections.Generic;
using XmdsCommon.Message;
using XmdsCommon.Plugin;
using XmdsCommonServer.Message;
using XmdsCommonServer.Plugin.Units;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.Skills;
using CommonAI.Zone.Instance;
using System;
using CommonLang.Vector;
using XmdsCommon.EditorData;
using CommonAI.Zone.Formula;
using CommonAI.Data;
using CommonAI;
using CommonAI.data;
using XmdsCommonSkill.Plugin.CardSkill;

namespace XmdsCommonServer.Plugin
{
    public partial class XmdsVirtual_Player : XmdsVirtual
    {
        /// <summary>
        /// 攻击记录.
        /// </summary>
        private HashMap<string, string> mAtkRecordMap = new HashMap<string, string>();

        /// <summary>
        /// PK值在线计时器.
        /// </summary>
        private TimeInterval<int> mPKValueCycleTimer = null;

        /// <summary>
        /// PK信息.
        /// </summary>
        private PKInfo mPKInfo = null;

        /// <summary>
        /// 药剂HP恢复.
        /// </summary>
        private ItemRecoveryTask mHPRecoveryTask = new ItemRecoveryTask();

        /// <summary>
        /// 宠物.
        /// </summary>
        private XmdsVirtual_Pet mPet = null;

		protected long mPkTime = 0;

        public XmdsVirtual_Player(XmdsInstancePlayer unit) : base(unit)
        {
            unit.OnRebirth += Unit_OnRebirth;
            unit.OnRemoved += Unit_OnRemoved;
        }

        private void Unit_OnRemoved(CommonAI.Zone.Instance.InstanceUnit unit)
        {
            //主人离开场景,移除宠物.
            if (mPet != null)
            {
                DismissPet();
            }
        }

        private void Unit_OnRebirth(CommonAI.Zone.Instance.InstanceUnit unit)
        {
            //重置遗言.
            SyncTestament(0);
        }

        public void SyncTestament(byte testamentID)
        {
            if (mProp.ServerData.BaseInfo.Testament != testamentID)
            {
                mProp.ServerData.BaseInfo.Testament = testamentID;
                SyncPlayerVisibleData();
                SendTestamentChangeEventB2C(testamentID);
            }
        }

		/** 获得宠物天赋加成 */
		public override int GetPetTalentAddition(UnitFateType type)
		{
			if(mPet != null && type == mPet.GetUnitFateType())
			{
				return mPet.GetPetTalentAddition(type);
			}

			return 0;
		}

		public override XmdsVirtual_Player GetPlayerUnit()
        {
            return this;
        }

        #region override.

        protected override void Init(bool pointLv)
        {
            InitPKCycleTimer();
            InitQuestData();
            //             InitQuestFlags();
            this.mProp.ServerData.PlayerEntered = true;

            //同步客户端可见信息.
            //设置发给别的玩家显示信息//
            PlayerVisibleDataB2C pvdb2c = new PlayerVisibleDataB2C();
            //avatar信息.
            pvdb2c.AvatarList = mProp.ServerData.AvatarList;
            //基础信息.
            pvdb2c.BaseInfo = mProp.ServerData.BaseInfo;
            //PK相关信息.
            pvdb2c.UnitPKInfo = mProp.ServerData.UnitPKInfo;
            //场景数据.
            pvdb2c.UnitSceneInfo = mProp.ServerData.UnitSceneInfo;

            mUnit.SetVisibleInfo(pvdb2c);

            mPKInfo = this.mProp.ServerData.UnitPKInfo;

            #region 宠物数据MOCK.
            //-------------------------------------------------.
            /*
            //宠物Mock数据.测试数据,当前宠物为无敌状态.
            PetData pd = new PetData();
            pd.PetConfig = new XmdsPetConifg();
            pd.PetConfig.Mode = XmdsPetConifg.XmdsPetFollowMode.ActiveAtk;
            pd.BaseInfo = new PetBaseInfo();
            XmdsUnitSkillInfo skillInfo = new XmdsUnitSkillInfo();
            List<GameSkill> l = new List<GameSkill>();
            GameSkill gs = new GameSkill();
            gs.SkillID = 100101;
            gs.SkillLevel = 1;
            gs.SkillType = GameSkill.XmdsSkillType.normalAtk;
            l.Add(gs);
            skillInfo.UnitSkills = l;
            pd.SkillInfo = skillInfo;
            UnitInfo info = XmdsBattleSkill.GetUnitInfo(DEFAULT_TEMPLATE_ID);
            this.mProp.ServerData.UnitPetData = pd;
            this.mProp.ServerData.UnitPetData.BaseInfo.level = 1;
            this.mProp.ServerData.UnitPetData.UnitProp = (info.Properties as XmdsUnitProperties).ServerData.Prop;
            this.mProp.ServerData.UnitPetData.UnitProp.MinPhy = 1;// 4803;
            this.mProp.ServerData.UnitPetData.UnitProp.MaxPhy = 1;// 4921;
            this.mProp.ServerData.UnitPetData.UnitProp.Hit = 710;
            this.mProp.ServerData.UnitPetData.UnitProp.Crit = 50;
            this.mProp.ServerData.UnitPetData.UnitProp.Dodge = 1;
            this.mProp.ServerData.UnitPetData.UnitProp.Rescrit = 949;
            this.mProp.ServerData.UnitPetData.UnitProp.Ac = 2229;
            this.mProp.ServerData.UnitPetData.UnitProp.Resist = 1500;
            this.mProp.ServerData.UnitPetData.UnitProp.HP = 1;
            */
            //-------------------------------------------------.
            #endregion

            //宠物数据.
            ChangePet(this.mProp.ServerData.UnitPetData);

            if (mProp.BotTestTemplate)
            {
                (this.mUnit as XmdsInstancePlayer).SendBotTestAutoFight();
            }
		}

        public override void doEvent(JSGCustomOpType type)
        {
            if(type == JSGCustomOpType.UpdateAutoBattleFlag)
            {
                SetAutoBattleB2C evt = new SetAutoBattleB2C();
                InstancePlayer playerUnit = mUnit as InstancePlayer;
                evt.isAutoBattle = playerUnit.IsGuard ? 1 : 0;
                this.mUnit.queueEvent(evt);
            }
        }

        public void OnUnitReEnter(UnitInfo temp, int force, int level, Vector2 enterPos)
        {
            SyncClientData();
        }

        protected override void SyncClientData()
        {
            base.SyncClientData();
            SyncPKValue(mPKInfo.CurPKValue, true);
        }

        public override void SyncBattlePropsFields(ulong mask)
        {
            if (mask != 0)
            {
                if (mBattlePropChangeEvt == null)
                {
                    mBattlePropChangeEvt = new PlayerBattlePropChangeEventB2C();
                }

                mBattlePropChangeEvt.Mask |= mask;
            }
        }

        public long getPkTime()
        {
            return CUtils.CurrentTimeMS - mPkTime;
        }

        public int getPkValue()
        {
            return mPKInfo.CurPKValue;
        }

		public override void OnUnitDead(XmdsVirtual killer)
		{
			//怪物死亡时,需要计算组队分享人员名单.
			mHateSystem.CalAtkAssistantList(false);
			base.OnUnitDead(killer);
		}


		public override int OnHit(XmdsVirtual attacker, AttackSource source)
        {
            int ret = base.OnHit(attacker, source);
            if (ret > 0 && attacker is XmdsVirtual_Player)
            {
                mPkTime = CUtils.CurrentTimeMS;
            }
            return ret;
        }

        public override void OnHitOthter(XmdsVirtual target)
        {
            if (mHateSystem.ContainsID(target.mUnit.ID) == false)
            {
                mHateSystem.AddTarget(target);
            }

            if (CalPKValue(target) == true)
            {
                if ((target is XmdsVirtual_Player ||
                    target is XmdsVirtual_SummonUnit ||
                    target is XmdsVirtual_Pet) &&
                    target.GetCurPKLevel() == PKLevel.White)
                {
                    string id = target.GetPlayerUUID();
                    if (id != this.GetPlayerUUID() && !string.IsNullOrEmpty(id))
                    {
                        //判断该单位是否有被攻击过.
                        if (mAtkRecordMap.ContainsKey(id) == false)
                        {
                            AtkRecordAdd(id);
                        }
                    }
                }
            }

            #region MOCK 恢复道具.

            //PropertyChangeEventR2B evt = new PropertyChangeEventR2B();
            //evt.ChangeType = PropertyChangeEventR2B.PropertyChangeType.HP;
            //evt.ChangeValue = 10000;
            //evt.Duration = 10000;
            //evt.ChangeValueType = PropertyChangeEventR2B.ValueType.Value;
            //OnRceivePropertyChangeEventR2B(evt);

            #endregion
        }

        public override bool TryLaunchSkill(InstanceUnit.SkillState skill, ref InstanceUnit.LaunchSkillParam param)
        {
            #region PK保护.

            //var pkprotect = IsInPKProtect(param.TargetUnitID);

            //if (pkprotect)
            //{
            //    SendMsgToClient(CommonAI.XmdsConstConfig.TIPS_IN_PK_PROTECT);
            //    return false;
            //}

            #endregion

            bool ret = base.TryLaunchSkill(skill, ref param);

            if (ret == true)
            {
                if (param.TargetUnitID != 0 && (this.mHateSystem.ContainsID(param.TargetUnitID) == false))
                {
                    InstanceUnit u = this.mUnit.Parent.getUnit(param.TargetUnitID);

                    if (u != null && u != this.mUnit)
                    {
                        if (!this.IsAllies(u.Virtual as XmdsVirtual, false))
                        {
                            this.mHateSystem.AddTarget(u.Virtual as XmdsVirtual);
                        }
                    }
                }
            }

            return ret;
        }

        public override void OnKillUnit(XmdsVirtual dead)
        {
            if (CalPKValue(dead) == true)
            {
                if (dead.IsPlayerUnit() &&
                    dead.GetCurPKLevel() == PKLevel.White &&
                    dead.GetPlayerUUID() != this.GetPlayerUUID())
                {
                    SyncPKValue(XmdsGameConfig.Instance.PK_KILL_ADD + this.mPKInfo.CurPKValue);
                }
            }


            #region Mock技能增删.
            /*
            List<GameSkill> ret = new List<GameSkill>();

            GameSkill gs = new GameSkill();
            gs.SkillID = 300010;
            gs.SkillLevel = ++skilllv;
            gs.SkillType = GameSkill.XmdsSkillType.active;
            gs.TalentSkillLevel = 1;
            ret.Add(gs);

            Mock_ReplaceSkill(ret);
            */
            #endregion
        }

        protected override void OnCombatStateChange(BattleStatus status)
        {
            base.OnCombatStateChange(status);

            if (status == BattleStatus.None) { mAtkRecordMap.Clear(); }

            /*测试怪物伤害信息.
            GetMonsterSufferDamageInfoC2B evt = new GetMonsterSufferDamageInfoC2B();
            evt.MonsterID = 3;
            (this.mUnit as XmdsInstancePlayer).OnReceiveGetMonsterSufferDamageInfoC2B(evt);
            */

        }

        protected override bool JudgeChangeCombatStateChange(BattleStatus status, byte reason)
        {
            //普通情况下,召唤物未出战斗状态,主人也处于战斗状态.
            if (status == BattleStatus.None && reason == 0)
            {
                if (mSummonList != null && mSummonList.Count > 0)
                {
                    for (int i = 0; i < mSummonList.Count; i++)
                    {
                        if (mSummonList[i].CombatState != BattleStatus.None)
                        {
                            return false;
                        }
                    }
                }
                //如果宠物在战斗状态,主人无法脱战.
                if (mPet != null && mPet.CombatState != BattleStatus.None)
                {
                    return false;
                }
            }

            return true;
        }

        protected override void CombatStateConnect(BattleStatus status, byte reason)
        {
            //主人进入战斗状态,影响召唤物.
            if (mSummonList != null && mSummonList.Count > 0)
            {

                for (int i = 0; i < mSummonList.Count; i++)
                {
                    mSummonList[i].SetCombatState(status);
                }
            }

            if (mPet != null && mPet.mUnit.IsDead() == false)
            {
                mPet.SetCombatState(status);
            }
        }

        public override string GetPlayerUUID()
        {
            return (mUnit as XmdsInstancePlayer).PlayerUUID;
        }

        public override bool IsMember(XmdsVirtual target, PKMode mode, bool includeSelf, bool onlyForTeam = false)
        {
            bool ret = false;

            if (this.mUnit == target.mUnit)
            {
                return includeSelf == true;
            }

            if (target.mUnit.Virtual is XmdsCommon.ZoneClient.XmdsClientVirtual.XmdsClientVirtual_Pet)
            {
                return true;//自动选取目标时选中宠物的bug
            }
            //非玩家单位统一走force.
            if (target.IsPlayerUnit() == false)
            {
                ret = this.mUnit.Force == target.mUnit.Force ? true : false;
            }
            else
            {
                switch (mode)
                {
                    case PKMode.Peace://和平模式使用默认出生的force.
						//只用阵营会导致,不是队友,给他加增益buff得情况
                        ret = this.mUnit.Force == target.mUnit.Force ? true : false;
						if (ret && onlyForTeam)
						{
							ret = this.IsTeamMember(target.GetPlayerUUID());
						}
						break;
                    case PKMode.force://阵营模式使用Camp.
                        ret = this.IsCampMember(target.GetForceID());
                        if (ret == false)
                        {
                            ret = this.IsTeamMember(target.GetPlayerUUID());
                        }
                        break;
                    case PKMode.Guild:
                        ret = this.IsGuildMember(target.GetGuildID());
                        if (ret == false)
                        {
                            ret = this.IsTeamMember(target.GetPlayerUUID());
                        }
                        break;
                    case PKMode.Team:
                        ret = this.IsTeamMember(target.GetPlayerUUID());
                        break;
                    case PKMode.All:
                        ret = (target.GetPlayerUUID() == this.GetPlayerUUID());
                        break;
                    case PKMode.Justice:
                        ret = target.GetCurPKLevel() == PKLevel.White ? true : false;
                        if (ret == false)
                        {
                            ret = this.IsTeamMember(target.GetPlayerUUID());
                        }
                        break;
                    case PKMode.Server:
                        ret = this.IsServerMember(target.GetServerID());
                        if (ret == false)
                        {
                            ret = this.IsTeamMember(target.GetPlayerUUID());
                        }
                        break;
                }
            }
            return ret;
        }

        public override void OnUpdateTriggerSkill(int intervalMS, bool slowRefresh)
        {
            base.OnUpdateTriggerSkill(intervalMS, slowRefresh);

            UpdatePKCycleTimer(intervalMS);
            UpdateItemRecoveryTask(intervalMS);
        }

        public override bool IsPlayerUnit() { return true; }

        protected override void Dispose()
        {
            mUnit.OnRebirth -= Unit_OnRebirth;
            mUnit.OnRemoved -= Unit_OnRemoved;
            CleanSummonList();

            if (mAtkRecordMap != null)
            {
                mAtkRecordMap.Clear();
            }

            mPet = null;

            base.Dispose();
        }

        public bool AllowUseAutoGuard()
        {
            bool ret = false;

            try
            {
                //机器人玩家默认可以使用自动战斗.
                if (mProp.BotTestTemplate)
                {
                    return true;
                }

                ret = mProp.ServerData.UnitSceneInfo.AllowAutoGuard;
            }
            catch (Exception error)
            {
                ret = true;
                FormatLog(CommonLang.Log.LoggerLevel.ERROR, "AllowUseAutoGuard Error:{0}", error.ToString());
            }

            return ret;
        }

        protected override void InitSceneInfo()
        {
            base.InitSceneInfo();


            switch (this.mUnit.GetSceneType())
            {
                case CommonAI.Data.SceneType.Dungeon://副本中索敌范围扩大.
                case CommonAI.Data.SceneType.DanTiao:
                case CommonAI.Data.SceneType.JJC:
                case CommonAI.Data.SceneType.GuildDungeon:
                case CommonAI.Data.SceneType.MengZhan:
                case CommonAI.Data.SceneType.FiveVFive:
                case CommonAI.Data.SceneType.GoblinTower:
                case CommonAI.Data.SceneType.SourceDungeon:
                case CommonAI.Data.SceneType.HaoYueJing:
                case CommonAI.Data.SceneType.GuildBoss:
                case CommonAI.Data.SceneType.SecretDungeon:
                case CommonAI.Data.SceneType.FightLevelUltra:
                case CommonAI.Data.SceneType.PickLotus:
                case CommonAI.Data.SceneType.CROSS_SERVER_NEW:
                case CommonAI.Data.SceneType.NCS_FengShen:
                case CommonAI.Data.SceneType.DEVIL:
                    (this.mUnit as XmdsInstancePlayer).SetGuardSearchRange(XmdsConfig.Instance.DUNGEON_AUTO_GUARD_RANGE);
                    break;
				case CommonAI.Data.SceneType.NCS_MutilCross:
				case CommonAI.Data.SceneType.NCS_DoubleCross:
					(this.mUnit as XmdsInstancePlayer).SetGuardSearchRange(XmdsConfig.Instance.PVP_AUTO_GUARD_RANGE);
                    break;
                default:
					(this.mUnit as XmdsInstancePlayer).SetGuardSearchRange(XmdsConfig.Instance.NORMALSCENE_AUTO_GUARD_RANGE);
					break;
            }

			//针对一些特殊的副本,设置拾取范围(全部改成手动拾取,所以这里没啥用了)
			//switch (this.mUnit.GetSceneType())
			//{
			//	case CommonAI.Data.SceneType.NCS_MutilCross:
			//	case CommonAI.Data.SceneType.NCS_DoubleCross:
			//	case CommonAI.Data.SceneType.NCS_FengShen:
			//	case CommonAI.Data.SceneType.DEVIL:
			//		this.mUnit.SetAutoPickRange(XmdsConstConfig.AUTOPICK_RANGE_PVP);
			//		break;
			//	default:					
			//		break;
			//}
		}

        #endregion

        #region private.

        private void SendTestamentChangeEventB2C(byte testamentID)
        {
            TestamentChangeEventB2C evt = new TestamentChangeEventB2C();
            evt.TestamentID = testamentID;
            this.mUnit.queueEvent(evt);
        }

        private void SendPKLevelChangeEventB2C(PKLevel lv)
        {
            PlayerPKLvChangeEventB2C evt = new PlayerPKLvChangeEventB2C();
            evt.CurLv = lv;
            this.mUnit.queueEvent(evt);
        }

        private void SendPKValueChangeEventB2C(int v)
        {
            PlayerPKValueChangeEventB2C evt = new PlayerPKValueChangeEventB2C();
            evt.CurPKValue = v;
            this.mUnit.queueEvent(evt);
        }

        /// <summary>
        /// PK值在线衰退计时器.
        /// </summary>
        private void InitPKCycleTimer()
        {
            mPKValueCycleTimer = new TimeInterval<int>(XmdsGameConfig.Instance.PK_VALUE_UPDATE_CYCLE);
            mPKValueCycleTimer.FirstTimeEnable = false;
        }

        /// <summary>
        /// 刷新计时器.
        /// </summary>
        /// <param name="intervalMS"></param>
        private void UpdatePKCycleTimer(int intervalMS)
        {
            if (mPKInfo != null && mPKInfo.CurPKValue > 0 && mPKValueCycleTimer.Update(intervalMS))
            {
                SyncPKValue(mPKInfo.CurPKValue - XmdsGameConfig.Instance.PK_VALUE_REDUCE);
            }
        }

        /// <summary>
        /// 攻击列表刷新.
        /// </summary>
        /// <param name="id"></param>
        private void AtkRecordAdd(string id)
        {
            mAtkRecordMap.Add(id, id);
            SyncPKValue(XmdsGameConfig.Instance.PK_ATK_ADD + mPKInfo.CurPKValue);
        }

        /// <summary>
        /// 同步PK值.
        /// </summary>
        /// <param name="v"></param>
        private void SyncPKValue(int v, bool refresh = false)
        {
            v = (int)CMath.getInRange(v, 0, int.MaxValue);

            if (mPKInfo.CurPKValue == v && refresh == false) { return; }

            mPKInfo.CurPKValue = v;

            //等于0时重置.
            if (mPKInfo.CurPKValue == 0 && mPKValueCycleTimer != null)
            {
                mPKValueCycleTimer.Reset();
            }

            SendPKValueChangeEventB2C(v);

            //等级变更时推送给客户端.
            PKLevel l;
            if (mPKInfo.CurPKValue == 0)
            {
                l = PKLevel.White;
            }
            else if (CMath.isIncludeEqual(mPKInfo.CurPKValue,
                XmdsGameConfig.Instance.PK_LEVEL_BLACK_RANGE[0],
                XmdsGameConfig.Instance.PK_LEVEL_BLACK_RANGE[1]))
            {
                l = PKLevel.Black;
            }
            else if (CMath.isIncludeEqual(mPKInfo.CurPKValue,
                XmdsGameConfig.Instance.PK_LEVEL_YELLOW_RANGE[0],
                XmdsGameConfig.Instance.PK_LEVEL_YELLOW_RANGE[1]))
            {
                l = PKLevel.Yellow;
            }
            else
            {
                l = PKLevel.Red;
            }

            if (mPKInfo.CurPKLevel != l)
            {
                mPKInfo.CurPKLevel = l;
                SyncPlayerVisibleData();
                SendPKLevelChangeEventB2C(l);
            }
        }

        private void UpdateItemRecoveryTask(int intervalMS)
        {
            mHPRecoveryTask.Update(intervalMS);
        }

        private bool IsInPKProtect(uint objID)
        {
            bool ret = false;

            //野外场景做判断.
            if (GetCurSceneType() != XmdsServerSceneData.NORMAL_MAP) { return ret; }

            //自己等级.
            int unitlv = this.GetUnitLv();
            //对方等级.
            int targetUnitLv = 0;

            uint id = objID;
            if (id != 0 && id != this.mUnit.ID)
            {
                var target = this.mUnit.Parent.getUnit(id);
                if (target != null)
                {
                    var uuid = (target.Virtual as XmdsVirtual).GetPlayerUUID();
                    var targetplayer = this.mUnit.Parent.getPlayerByUUID(uuid);

                    if (targetplayer != null)
                    {
                        targetUnitLv = (targetplayer.Virtual as XmdsVirtual).GetUnitLv();
                        //小于等于保护等级,不受伤害.
                        if (targetUnitLv <= XmdsConfig.Instance.PK_PROTECT_LV || unitlv <= XmdsConfig.Instance.PK_PROTECT_LV)
                        {
                            ret = true;
                        }
                    }
                }
            }

            return ret;
        }

        //消耗过大,暂时屏蔽,后期考虑优化方案
        public override bool IsAttackable(XmdsVirtual attacker)
        {
            //只在野外地图下判断.
            //if (GetCurSceneType() == XmdsServerSceneData.NORMAL_MAP)
            //{
            //    //自己等级.
            //    int unitLv = GetUnitLv();
            //    int attackerLv = 0;

            //    string uuid = attacker.GetPlayerUUID();
            //    var v = this.mUnit.Parent.getPlayerByUUID(uuid);

            //    if (v != null && v != this.mUnit)
            //    {
            //        attackerLv = (v.Virtual as XmdsVirtual_Player).GetUnitLv();

            //        if (attackerLv <= XmdsConfig.Instance.PK_PROTECT_LV || unitLv <= XmdsConfig.Instance.PK_PROTECT_LV)
            //        {
            //            return false;
            //        }
            //    }
            //}

            return true;
        }

        public class ItemRecoveryTask
        {
            public const int CYCLE_TIME = 500;
            private XmdsVirtual mOwner;
            private PropertyChangeEventR2B mEvt;
            private int mLifeTime = -1;
            private int mPassTime;
            private int mTimes = 1;
            private bool showFloatTips = false;
            public ItemRecoveryTask()
            {

            }

            public void Init(XmdsVirtual zv, PropertyChangeEventR2B evt, bool show)
            {
                mOwner = zv;
                mEvt = evt;
                mPassTime = CYCLE_TIME;
                //剩余时间.
                mLifeTime = (int)(evt.TimestampMS - TimeUtil.GetTimestampMS());
                //每秒次数.
                mTimes = (evt.Duration / CYCLE_TIME);
                showFloatTips = show;
            }

            public void Update(int intervalMS)
            {
                if (!IsEnd())
                {
                    if (mPassTime >= CYCLE_TIME)
                    {
                        mPassTime -= CYCLE_TIME;

                        switch (mEvt.ChangeType)
                        {
                            case PropertyChangeEventR2B.PropertyChangeType.HP:
                                mOwner.AddHP(mEvt.ChangeValueType, (mEvt.ChangeValue * 1.0f / mTimes), showFloatTips);
                                break;
                            default: break;
                        }
                    }
                    mPassTime += intervalMS;
                    mLifeTime -= intervalMS;
                }
            }

            private bool IsEnd()
            {
                return (mLifeTime < 0);
            }
        }
        #endregion

        #region SummonUnit.

        private List<XmdsVirtual_SummonUnit> mSummonList = new List<XmdsVirtual_SummonUnit>();

        public void AddSummonUnitList(XmdsVirtual_SummonUnit unit)
        {
            mSummonList.Add(unit);
            unit.mUnit.OnDead += MUnit_OnDead;
        }

        private void MUnit_OnDead(CommonAI.Zone.Instance.InstanceUnit unit, CommonAI.Zone.Instance.InstanceUnit attacker)
        {
            XmdsVirtual_SummonUnit v = unit.Virtual as XmdsVirtual_SummonUnit;

            if (v != null && mSummonList != null)
            {
                unit.OnDead -= MUnit_OnDead;
                mSummonList.Remove(v);
            }
        }

        public int GetSummonUnitListCount()
        {
            return mSummonList.Count;
        }

        public XmdsVirtual_SummonUnit GetFirstTimesupSummonUnit()
        {
            if (mSummonList.Count > 0)
            {
                return mSummonList[0];
            }
            return null;
        }

        public void CleanSummonList()
        {
            if (mSummonList != null && mSummonList.Count > 0)
            {
                for (int i = 0; i < mSummonList.Count; i++)
                {
                    mSummonList[i].mUnit.OnDead -= MUnit_OnDead;
                }

                mSummonList.Clear();
            }
        }

        #endregion

        #region Pet.        

        public XmdsVirtual_Pet GetPet()
        {
            return mPet;
        }

        public override InstanceUnit GetPetUnit()
        {
            if(mPet != null)
             return mPet.mUnit;
            return null;
        }

        private void SummonPetData(PetData data)
        {
            if (data == null) { return; }

            var pos = mUnit.Parent.PathFinder.FindNearMoveableNode(
                      mUnit.X,
                      mUnit.Y,
                      XmdsConfig.Instance.PET_IDLE_FOLLOW_MAX_DISTANCE, true);
            if (pos == null)
            {
                log.Error(" SummonPetData  pos = null");
                return;
            }
            UnitInfo info = XmdsBattleSkill.GetUnitInfo(XmdsConstConfig.DEFAULT_PET_TEMPLATE_ID);
			if(info == null)
			{
				log.Warn("找不到宠物模板:" + XmdsConstConfig.DEFAULT_PET_TEMPLATE_ID);
				return ;
			}

            AddUnitEvent aue = null;
            XmdsUnitProperties prop = info.Properties as XmdsUnitProperties;

            //单位战斗属性赋值.
            //单位等级.
            prop.ServerData.BaseInfo.UnitLv = data.BaseInfo.level;
            //进阶等级.
            prop.ServerData.BaseInfo.StateLv = data.BaseInfo.StateLv;

            //能力赋值.
            prop.ServerData.Prop = data.UnitProp;
            //技能赋值.
            prop.ServerData.Skills = data.SkillInfo;

            var unit = (mUnit.Parent.AddUnit(
                        info, info.Name,
                        mUnit.Force, data.BaseInfo.level,
                        pos.PosX,
                        pos.PosY,
                        mUnit.Direction,
                        out aue,
                        mUnit)) as XmdsInstancePet;

            var petVirtual = (unit.Virtual) as XmdsVirtual_Pet;

            data.BaseInfo.MasterID = this.mUnit.ID;
            petVirtual.InitVisibleData(data.BaseInfo);
            petVirtual.SetMaster(this);
            petVirtual.SetFollowMode(data.PetConfig.Mode);

            //设置宠物.
            mPet = petVirtual;

            //设置主人.
            unit.Master = this.mUnit;

            //宠物死亡后,清空引用避免内存泄露.
            unit.OnDead += PetUnit_OnDead;
        }

        private void PetUnit_OnDead(InstanceUnit unit, InstanceUnit attacker)
        {
            unit.OnDead -= PetUnit_OnDead;
            mPet = null;
        }

        /// <summary>
        /// 遣散宠物.
        /// </summary>
        private void DismissPet()
        {
            if (mPet != null)
            {
                this.mUnit.Parent.RemoveObjectByID(mPet.mUnit.ID);
                mPet = null;
            }
        }

        private void ChangePet(PetData data)
        {
            if (mPet != null)
            {
                DismissPet();
            }

            //召唤宠物.
            SummonPetData(data);
        }

        //宠物基础属性变更.
        private void UpdatePetBaseInfo(PetBaseInfo info)
        {
            //基础信息更新.
            if (mPet != null)
            {
                mPet.UpdateBaseInfo(info);
            }
        }

        //所有宠物相关属性变更.
        private void UpdatePetData(PetData data)
        {
            if (mPet != null)
            {
                //更新基础信息.
                UpdatePetBaseInfo(data.BaseInfo);
                //属性变更.
                mPet.UpdatePetProps(data.UnitProp);
            }
        }

        private void UpdatePetSkillInfo(PetSkillChangeEventR2B evt)
        {
            if (mPet != null)
            {
                mPet.OnReceivePetSkillChangeEventR2B(evt);
            }
        }

		#endregion
	}
}