using CommonAI.Data;
using CommonAI.Zone.Instance;
using System.Collections.Generic;
using XmdsCommon.Message;
using XmdsCommon.Plugin;
using XmdsCommonServer.Message;
using XmdsCommonServer.Plugin.Units;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.Skills;

namespace XmdsCommonServer.Plugin
{
    public class XmdsVirtual_Pet : XmdsVirtual
    {

        /// <summary>
        /// 药剂HP恢复.
        /// </summary>
        private XmdsVirtual_Player.ItemRecoveryTask mHPRecoveryTask = new XmdsVirtual_Player.ItemRecoveryTask();
        /// <summary>
        /// 药剂MP恢复.
        /// </summary>
        private XmdsVirtual_Player.ItemRecoveryTask mMPRecoveryTask = new XmdsVirtual_Player.ItemRecoveryTask();
        /// <summary>
        /// 药剂HPMP同时恢复.
        /// </summary>
        private XmdsVirtual_Player.ItemRecoveryTask mHPMPRecoveryTask = new XmdsVirtual_Player.ItemRecoveryTask();

		private XmdsVirtual mMaster = null;

		public XmdsVirtual_Pet(XmdsInstancePet unit) : base(unit)
        {

        }

        public void InitVisibleData(PetBaseInfo info)
        {
            PetVisibleDataB2C data = new PetVisibleDataB2C();
            data.BaseInfo = info;
            mUnit.Level = info.level;
            mUnit.SetVisibleInfo(data);
        }

        public void SetMaster(XmdsVirtual master)
        {
            mMaster = master;

            if (this.mUnit != null)
            {
                (this.mUnit as XmdsInstancePet).SummonerUnit = mMaster.mUnit;
            }

            master.OnHandleCombatChangeEvent += Master_OnHandleCombatChangeEvent;

			//首次需要同步战斗状态.
			Master_OnHandleCombatChangeEvent(master.CombatState);
		}

        private void Master_OnHandleCombatChangeEvent(BattleStatus status)
        {
            (this.mUnit as XmdsInstancePet).OnMasterChangeCombatStatus(status);
        }

        public override string GetPlayerUUID()
        {
            InstanceUnit u = (mUnit as InstancePet).Master;

            if (u != null)
            {
                return ((u.Virtual) as XmdsVirtual).GetPlayerUUID();
            }

            return base.GetPlayerUUID();
        }

        public override int GetForceID()
        {
            InstanceUnit u = (mUnit as InstancePet).Master;

            if (u != null)
            {
                return ((u.Virtual) as XmdsVirtual).GetForceID();
            }

            return base.GetForceID();
        }

        public override string GetGuildID()
        {
            InstanceUnit u = (mUnit as InstancePet).Master;
            if (u != null)
            {
                return ((u.Virtual) as XmdsVirtual).GetGuildID();
            }

            return base.GetGuildID();
        }

        public override int GetServerID()
        {
            InstanceUnit u = (mUnit as InstancePet).Master;
            if (u != null)
            {
                return ((u.Virtual) as XmdsVirtual).GetServerID();
            }

            return base.GetServerID();
        }

        public override PKLevel GetCurPKLevel()
        {
            InstanceUnit u = (mUnit as InstancePet).Master;

            if (u != null)
            {
                return ((u.Virtual) as XmdsVirtual).GetCurPKLevel();
            }

            return base.GetCurPKLevel();
        }

        public override PKMode GetCurPKMode()
        {
            InstanceUnit u = (mUnit as InstancePet).Master;

            if (u != null)
            {
                return ((u.Virtual) as XmdsVirtual).GetCurPKMode();
            }
            return base.GetCurPKMode();
        }

        public override bool IsMember(XmdsVirtual target, PKMode mode, bool includeSelf, bool onlyForTeam)
        {
            if (includeSelf == true && this.mUnit == target.mUnit)
            {
                return true;
            }

            InstanceUnit u = (this.mUnit as InstancePet).SummonerUnit;

            if (u != null)
            {
                XmdsVirtual zv = u.Virtual as XmdsVirtual;
                return zv.IsMember(target, mode, includeSelf, onlyForTeam);
            }

            return base.IsMember(target, mode, includeSelf, onlyForTeam);
        }

        public bool IsMaster(XmdsVirtual target)
        {
            bool ret = false;

            if ((this.mUnit as InstancePet).Master == target.mUnit)
            {
                ret = true;
            }

            return ret;
        }

        public XmdsVirtual GetMaster()
        {
            return mMaster;
        }

		public override uint GetMasterID()
		{
			if(this.mMaster != null)
			{
				return this.mMaster.mUnit.ID;
			}

			return 0;
		}

		public override InstanceUnit GetMasterUnit()
		{
			if (this.mMaster != null)
			{
				return this.mMaster.mUnit;
			}

			return null;
		}

		public override void OnKillUnit(XmdsVirtual dead)
        {
            if (CalPKValue(dead) == true)
            {
                if (dead.IsPlayerUnit() &&
                    dead.GetCurPKLevel() == PKLevel.White)
                {
                    XmdsInstancePlayer zip = (mUnit as InstancePet).Master as XmdsInstancePlayer;

                    if (zip != null)
                    {
                        (zip.Virtual as XmdsVirtual).OnKillUnit(dead);
                    }
                }
            }
        }

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

            var zv = GetMaster();

            if (zv != null)
            {
                zv.OnHitOthter(target);
            }
        }

        public override bool IsPlayerUnit()
        {
            bool ret = false;

            InstanceUnit u = (mUnit as InstancePet).Master;

            if (u is XmdsInstancePlayer)
            {
                ret = true;
            }

            return ret;
        }

        public override XmdsVirtual_Player GetPlayerUnit()
        {
            XmdsVirtual_Player ret = null;

            InstanceUnit u = (mUnit as InstancePet).Master;
            if (u != null && u is XmdsInstancePlayer)
            {
                ret = u.Virtual as XmdsVirtual_Player;
            }

            return ret;
        }

        public void UpdateBaseInfo(PetBaseInfo info)
        {
            mUnit.Level = info.level;
            mProp.ServerData.BaseInfo.UnitLv = info.level;
            var p = GetMaster();
            if (p != null)
            {
                //宿主ID.
                info.MasterID = p.mUnit.ID;
            }

            if (this.mUnit.VisibleInfo is PetVisibleDataB2C)
            {
                //服务端数据保存更新.
                PetVisibleDataB2C pvd = this.mUnit.VisibleInfo as PetVisibleDataB2C;
                pvd.BaseInfo = info;

                //推送变更协议.
                PetBaseInfoChangeEventB2C evt = new PetBaseInfoChangeEventB2C();
                evt.BaseInfo = info;
                this.mUnit.queueEvent(evt);
            }
        }
		 
        public void UpdatePetProps(XmdsUnitProp prop)
        {
            XmdsUnitPropEventB2C evt = new XmdsUnitPropEventB2C();
            evt.Props = prop;
            OnPlayerPropertiesChanged(evt);
        }

        public void OnReceivePetSkillChangeEventR2B(PetSkillChangeEventR2B evt)
        {
            if (evt != null)
            {
                switch (evt.OperateID)
                {
                    case PlayerSkillChangeEventR2B.SkillOperate.Replace:
                        this.mSkillHelper.ReplaceSkill(evt.SkillList);
                        break;
                    case PlayerSkillChangeEventR2B.SkillOperate.Add:
                        this.mSkillHelper.AddSkill(evt.SkillList);
                        break;
                    case PlayerSkillChangeEventR2B.SkillOperate.Remove:
                        this.mSkillHelper.RemoveSkill(evt.SkillList);
                        break;
                    case PlayerSkillChangeEventR2B.SkillOperate.Reset:
						//this.mSkillHelper.ResetSkill(evt.SkillList);
						this.ResetSkill(evt.SkillList);
						break;
                    default: break;
                }

            }
        }

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

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

        public void OnRceivePropertyChangeEventR2B(PropertyChangeEventR2B evt)
        {
            FormatLog("OnRceivePropertyChangeOrder", null);

            bool success = false;

            switch (evt.ChangeType)
            {
                case PropertyChangeEventR2B.PropertyChangeType.HP:

                    if (evt.Duration > 0)
                    {
                        mHPMPRecoveryTask.Init(this, evt, true);
                    }
                    else
                    {
                        success = AddHP(evt.ChangeValueType, evt.ChangeValue, false);
                    }
                    break;
                case PropertyChangeEventR2B.PropertyChangeType.NPC:
                    if (this.mUnit.CurrentHP != this.mUnit.MaxHP ||
                        this.mUnit.CurrentMP != this.mUnit.MaxMP)
                    {
                        this.AddHP(this.mUnit.MaxHP, null, false);
                        this.AddMP(this.mUnit.MaxMP, null, false, true);
                    }
                    break;
                default: break;
            }
        }

        public void OnReceivePetFollowModeChangeEventR2B(PetFollowModeChangeEventR2B evt)
        {
            SetFollowMode(evt.mode);
        }

        public void SetFollowMode(XmdsCommon.Plugin.XmdsPetConifg.XmdsPetFollowMode mode)
        {
            (this.mUnit as XmdsInstancePet).SetFollowMode(mode);
        }

        //protected override void CombatStateConnect(CombatStateChangeEvent.BattleStatus status, byte reason)
        //{
        //    var v = GetMaster();

        //    if (v != null)
        //    {
        //        v.SetCombatState(status, reason);
        //    }
        //}

        protected override void Dispose()
        {
            if (mMaster != null)
            {
                mMaster.OnHandleCombatChangeEvent -= Master_OnHandleCombatChangeEvent;
                mMaster = null;
            }

			base.Dispose();
        }

        public override bool IsAttackable(XmdsVirtual attacker)
        {
            var v = GetMaster();

            if (v != null)
            {
                return v.IsAttackable(attacker);
            }

            return base.IsAttackable(attacker);
        }

        public override bool TeamMemberVisible
        {
            get
            {
                if (mMaster != null)
                {
                    return (!mMaster.mUnit.IsDead());
                }

                return base.TeamMemberVisible;
            }

            set
            {
                base.TeamMemberVisible = value;
            }
        }
	}
}