using CommonAI.Zone;
using CommonAI.Zone.Helper;
using CommonAI.Zone.Instance;
using CommonAI.Zone.ZoneEditor;
using CommonLang;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XmdsCommon.EditorData;
using XmdsCommon.Message;
using XmdsCommon.Plugin;
using XmdsCommonServer.Message;
using XmdsCommonServer.Plugin.Scene;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.Skills;

namespace XmdsCommonServer.Plugin
{

    partial class XmdsVirtual_Player
    {
        #region 协议监听.

        public override void ReceiveMsgR2B(object status)
        {
            if (status == null)
            {
                FormatLog("ReceiveMsgR2B status is null", null);
                return;
            }

            if (status is XmdsUnitPropEventB2C)
            {
                OnPlayerPropertiesChanged(status as XmdsUnitPropEventB2C);
            }
            else if (status is PlayerSkillChangeEventR2B)
            {
                OnPlayerSkillsChanged(status as PlayerSkillChangeEventR2B);
            }
            else if (status is XmdsUnitBaseInfoEventB2C)
            {
                OnPlayerBaseInfoChanged(status as XmdsUnitBaseInfoEventB2C);
            }
            else if (status is PlayerRebirthEventR2B)
            {
                OnReceivePlayerRebirthOrder(status as PlayerRebirthEventR2B);
            }
            else if (status is PlayerSummonMountEventR2B)
            {
                OnReceivePlayerSummonMountEventR2B(status as PlayerSummonMountEventR2B);
            }
            else if (status is PlayAvatarEventB2C)
            {
                OnReceivePlayerAvatarEventB2C(status as PlayAvatarEventB2C);
            }
            else if (status is SyncPlayerInventorySizeEventR2B)
            {
                OnReceiveSyncPlayerInventorySizeEventR2B(status as SyncPlayerInventorySizeEventR2B);
            }
            else if (status is TeamInfoEventR2B)
            {
                OnReceiveTeamInfoEventR2B(status as TeamInfoEventR2B);
            }
            else if (status is TeamDataEventR2B)
            {
                OnReceiveTeamDataEventR2B(status as TeamDataEventR2B);
            }
            else if (status is PlayerPKLevelChangeEventR2B)
            {
                OnReceivePlayerPKLvChangeEventR2B(status as PlayerPKLevelChangeEventR2B);
            }
            else if (status is PlayerPKModeChangeEventR2B)
            {
                OnReceivePlayerPKModeChangeEventR2B(status as PlayerPKModeChangeEventR2B);
            }
            else if (status is PlayerPKValueChangeEventR2B)
            {
                OnReceivePlayerPKValueChangeEventR2B(status as PlayerPKValueChangeEventR2B);
            }
            else if (status is PropertyChangeEventR2B)
            {
                OnRceivePropertyChangeEventR2B(status as PropertyChangeEventR2B);
            }
            else if (status is PetDataChangeEventR2B)
            {
                OnReceivePetDataChangeEventR2B(status as PetDataChangeEventR2B);
            }
            else if (status is PetBaseInfoChangeEventR2B)
            {
                OnReceivePetBaseInfoChangeEventR2B(status as PetBaseInfoChangeEventR2B);
            }
            else if (status is PetSkillChangeEventR2B)
            {
                OnReceivePetSkillChangeEventR2B(status as PetSkillChangeEventR2B);
            }
            else if (status is TeamInventorySizeChangeEventR2B)
            {
                OnReceiveTeamInventorySizeChangeEventR2B(status as TeamInventorySizeChangeEventR2B);
            }
            else if (status is PetPropertyChangeEventR2B)
            {
                OnReceivePetPropertyChangeEventR2B(status as PetPropertyChangeEventR2B);
            }
            else if (status is PetFollowModeChangeEventR2B)
            {
                OnReceivePetFollowModeChangeEventR2B(status as PetFollowModeChangeEventR2B);
            }
        }


        /// <summary>
        /// 基础属性变更.
        /// </summary>
        private void OnPlayerBaseInfoChanged(XmdsUnitBaseInfoEventB2C evt)
        {

            if (evt != null && evt.Props != null)
            {
                FormatLog("OnPlayerBaseInfoChanged", null);
                //重置基础信息.
                InitBaseInfo(evt.Props);
                SyncPlayerVisibleData();
                //广播级事件统一由游戏服转给客户端广播.
                this.mUnit.queueEvent(evt);
            }
            else
            {
                FormatLog("OnPlayerBaseInfoChanged Error :XmdsUnitBaseInfoEventB2C.Props is null", null);
            }

        }

        /// <summary>
        /// 重生通知.
        /// </summary>
        private void OnReceivePlayerRebirthOrder(PlayerRebirthEventR2B msg)
        {
            FormatLog("OnReceivePlayerRebirthOrder", null);
            if (this.mUnit.IsDead() == true)
            {
                //Console.WriteLine(" ------- 复活------ " + msg.type);
                switch (msg.type)
                {
                    case 1://原地复活.
                        if(this.mUnit.GetSceneType() >= CommonAI.Data.SceneType.CROSS_SERVER_NEW)
                        {
                            DoRebirthInStartRegion(msg);
                        }
                        else
                        {
                            this.mUnit.startRebirth(msg.HP, msg.MP);
                            this.mUnit.queueEvent(msg.Callback);
                        }                        
                        break;
                    case 2://出生点复活.
                        DoRebirthInStartRegion(msg);
                        break;
                    case 3://复活点复活.
                        {
                            XmdsServerScene zss = this.mUnit.Parent as XmdsServerScene;
                            ZoneRegion ret = zss.GetNearestRebirthRegion(this.mUnit.X, this.mUnit.Y, this.mUnit.Force);

                            if (ret == null)
                            {
                                DoRebirthInStartRegion(msg);
                            }
                            else
                            {
                                this.mUnit.transport(ret.X, ret.Y);
                                this.mUnit.startRebirth(msg.HP, msg.MP);
                                this.mUnit.queueEvent(msg.Callback);
                            }
                        }
                        break;
                    case 4://技能复活.
                        this.mUnit.startRebirth(msg.HP, msg.MP);
                        break;
                    case 5://随机复活点复活
                        {
                            XmdsServerScene zss = this.mUnit.Parent as XmdsServerScene;
                            ZoneRegion ret = zss.GetRandomRebirthRegion(this.mUnit.Force);

                            if (ret == null)
                            {
                                DoRebirthInStartRegion(msg);
                            }
                            else
                            {
                                this.mUnit.transport(ret.X, ret.Y);
                                this.mUnit.startRebirth(msg.HP, msg.MP);
                                this.mUnit.queueEvent(msg.Callback);
                            }
                        }
                        break;
                    default:
                        break;
                }
            }

        }

        private void DoRebirthInStartRegion(PlayerRebirthEventR2B msg)
        {
            EditorScene es = this.mUnit.Parent as EditorScene;
            ZoneRegion zr = es.GetEditStartRegion(this.mUnit.Force);

            if (zr != null)
            {
                this.mUnit.transport(zr.X, zr.Y);
                //log.WarnFormat("无法找到场景ID为{0}阵营为{1}的出生点", es.Data.ID, this.mUnit.Force);
            }
            else
            {
                this.mUnit.transport(mBirthPosX, mBirthPosY);
            }

            this.mUnit.startRebirth(msg.HP, msg.MP);
            this.mUnit.queueEvent(msg.Callback);
        }

        /// <summary>
        /// 援救通知.
        /// </summary>
        private void OnReceivePlayerSaveEventR2B(PlayerSaveEventR2B msg)
        {
            FormatLog("OnReceivePlayerSaveEventR2B", null);

            if (msg.Saver == null || msg.Decedent == null) { return; }

            mUnit_OnPickUnit(msg.Saver, msg.Decedent, msg.SaveTime);
        }

        /// <summary>
        /// 召唤坐骑通知.
        /// </summary>
        private void OnReceivePlayerSummonMountEventR2B(PlayerSummonMountEventR2B evt)
        {
            //((this.mUnit.Parent as XmdsServerScene).mListener as XmdsZoneNode)
            XmdsServerScene scene = this.mUnit.Parent as XmdsServerScene;
            
            FormatLog("OnReceivePlayerSummonMountEventR2B", null);

            //需要判断一些特殊状态.晕眩,变身,战斗中等等.
            if (evt.IsSummonMount == true)
            {
                bool canRiding = scene.Data.canRiding;
                if (!canRiding || this.IsInPVP() || this.IsInPVE()) 
                {
                    return;
                }
                
                //战斗状态下无法上马或处于异常状态下.

                if (IsInDebuffStatus() || IsBusy() || this.mUnit.IsDead())
                {
                    SendMsgToClient(CommonAI.XmdsConstConfig.TIPS_CAN_NOT_RIDE);
                    return;
                }

                if(this.mUnit.CurrentActionStatus == UnitActionStatus.DaZuo || this.mUnit.CurrentActionStatus == UnitActionStatus.ClearYaoQi
					|| this.mUnit.CurrentActionStatus == UnitActionStatus.Pick || this.mUnit.CurrentActionStatus == UnitActionStatus.DaZuoRecoveryAttr)
                {
                    this.mUnit.startIdle(true);
					//this.mUnit.SendForceSync();
                }

                //清除与坐骑状态冲突的BUFF.
                ClearSPBuffState();
            }

            this.StartSummonMount(evt.TimeMS, evt.IsSummonMount, "summonmount");
        }

        /// <summary>
        /// 清除与坐骑状态冲突的BUFF(隐身).
        /// </summary>
        private void ClearSPBuffState()
        {


            //取当前所有BUFF,判断如果有隐身BUFF立即解除该BUFF.
            using (var buffList = ListObjectPool<InstanceUnit.BuffState>.AllocAutoRelease())
            {

                InstanceUnit.BuffState bfs = null;
                List<XmdsBuffVirtual> list = null;
                XmdsBuffProperties prop = null;
                BuffTemplate bt = null;

                this.mUnit.GetAllBuffStatus(buffList);

                if (buffList != null && buffList.Count > 0)
                {
                    for (int i = 0; i < buffList.Count; i++)
                    {
                        bfs = buffList[i];
                        bt = bfs.Data;
                        prop = bt.Properties as XmdsBuffProperties;
                        list = prop.GetBuffVirtualList();

                        if (list != null && list.Count != 0)
                        {

                            for (int k = 0; k < list.Count; k++)
                            {
                                UnitBuff ub = list[k] as UnitBuff;
                                if (ub.GetAbilityID() == (int)XmdsBuffProperties.XmdsBuffAbility.Stealth)
                                {
                                    this.mUnit.removeBuff(bt.ID, "summonmount");
                                }
                            }

                        }


                    }
                }

            }

        }

        /// <summary>
        /// 收到外观变更.
        /// </summary>
        private void OnReceivePlayerAvatarEventB2C(PlayAvatarEventB2C evt)
        {
			string extData = "";
			foreach (XmdsAvatarInfo temp in evt.AvatarList)
			{
				extData += (temp.PartTag + ", " + temp.FileName + "; ");
			}

			//log.Info("OnReceivePlayAvatarEventB2C: " + this.GetPlayerUUID() + ", " + extData);

            if (evt != null)
            {
                this.mProp.ServerData.AvatarList = evt.AvatarList;
                SyncPlayerVisibleData();
                this.mUnit.queueEvent(evt);
            }
        }

        /// <summary>
        /// 收到同步可用背包格子数量.
        /// </summary>
        /// <param name="evt"></param>
        private void OnReceiveSyncPlayerInventorySizeEventR2B(SyncPlayerInventorySizeEventR2B evt)
        {
            FormatLog("OnReceiveSyncPlayerInventorySizeEventR2B", null);

            SetInventorySize(evt.Size);
        }

        /// <summary>
        /// 单位PK等级变更.
        /// </summary>
        /// <param name="evt"></param>
        private void OnReceivePlayerPKLvChangeEventR2B(PlayerPKLevelChangeEventR2B evt)
        {
            FormatLog("OnReceivePlayerPKLvChangeEventR2B", null);

            this.mProp.ServerData.UnitPKInfo.CurPKLevel = evt.CurPKLv;
            SyncPlayerVisibleData();
            PlayerPKLvChangeEventB2C evtb2c = new PlayerPKLvChangeEventB2C();
            evtb2c.CurLv = evt.CurPKLv;
            this.mUnit.queueEvent(evtb2c);
        }

        /// <summary>
        /// 单位PK模式变更.
        /// </summary>
        /// <param name="evt"></param>
        private void OnReceivePlayerPKModeChangeEventR2B(PlayerPKModeChangeEventR2B evt)
        {
            log.Info("OnReceivePlayerPKLvChangeEventR2B:" + this.mUnit.PlayerUUID + ", " + evt.CurPKMode);

            this.mProp.ServerData.UnitPKInfo.CurPKMode = evt.CurPKMode;
            SyncPlayerVisibleData();
            this.mUnit.queueEvent(new PlayerPKModeChangeEventB2C(this.mUnit.ID, evt.CurPKMode));
        }

        protected virtual void OnReceivePlayerPKValueChangeEventR2B(PlayerPKValueChangeEventR2B evt)
        {
            FormatLog("OnReceivePlayerPKValueChangeEventR2B", null);
            int c = this.mProp.ServerData.UnitPKInfo.CurPKValue + evt.ChangeValue;
            SyncPKValue(c);
        }

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

            bool success = false;

            switch (evt.ChangeType)
            {
                case PropertyChangeEventR2B.PropertyChangeType.HP:
                    //药水效果加成
                    int valueExt = (int)(mProp.ServerData.BaseInfo.potionAddition * evt.ChangeValue);
                    evt.ChangeValue = evt.ChangeValue + valueExt;

                    if (evt.Duration > 0)
                    {
                        mHPRecoveryTask.Init(this, evt, true);
                    }
                    else
                    {
                        success = AddHP(evt.ChangeValueType, evt.ChangeValue, false);
                    }
                    break;
                case PropertyChangeEventR2B.PropertyChangeType.NPC:
                    {
                        bool sendEvent = false;

                        //单位未满血满蓝.
                        if (this.mUnit.IsDead() == false &&
                            ((this.mUnit.CurrentHP != this.mUnit.MaxHP) ||
                            (this.mUnit.CurrentMP != this.mUnit.MaxMP)))
                        {
                            DoCure();
                            sendEvent = true;
                        }

                        //宠物未满血满蓝.
                        if (mPet != null && mPet.mUnit.IsDead() == false &&
                            ((this.mPet.mUnit.CurrentHP != this.mPet.mUnit.MaxHP) ||
                            (this.mPet.mUnit.CurrentMP != this.mPet.mUnit.MaxMP)))
                        {
                            mPet.DoCure();
                            sendEvent = true;
                        }
                        //召唤物.
                        if (mSummonList != null && mSummonList.Count > 0)
                        {
                            XmdsVirtual_SummonUnit zv = null;

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

                                if (zv.mUnit.IsDead() == false &&
                                   ((zv.mUnit.CurrentHP != zv.mUnit.MaxHP ||
                                    zv.mUnit.CurrentMP != zv.mUnit.MaxMP)))
                                {
                                    sendEvent = true;
                                    mSummonList[i].DoCure();
                                }
                            }
                        }

                        if (sendEvent)
                        {
                            this.mUnit.queueEvent(new NPCCureEventB2C());
                        }
                    }
                    break;
                default: break;
            }
        }

        private void OnReceivePetDataChangeEventR2B(PetDataChangeEventR2B evt)
        {
            FormatLog("OnReceivePetDataChangeEventR2B", null);

            switch (evt.OpType)
            {
                case PetDataChangeEventR2B.PetDataChangeType.Add:
                    ChangePet(evt.Data);
                    break;
                case PetDataChangeEventR2B.PetDataChangeType.Delete:
                    DismissPet();
                    break;
                case PetDataChangeEventR2B.PetDataChangeType.Replace:
                    ChangePet(evt.Data);
                    break;
                case PetDataChangeEventR2B.PetDataChangeType.Reset:
                    UpdatePetData(evt.Data);
                    break;
            }

        }

        private void OnReceivePetBaseInfoChangeEventR2B(PetBaseInfoChangeEventR2B evt)
        {
            FormatLog("OnReceivePetBaseInfoChangeEventR2B", null);

            UpdatePetBaseInfo(evt.BaseInfo);
        }

        private void OnReceivePetSkillChangeEventR2B(PetSkillChangeEventR2B evt)
        {
            FormatLog("OnReceivePetSkillChangeEventR2B", null);

            UpdatePetSkillInfo(evt);
        }

        private void OnReceiveTeamInventorySizeChangeEventR2B(TeamInventorySizeChangeEventR2B evt)
        {
            FormatLog("OnReceivePetSkillChangeEventR2B", null);
            this.mProp.ServerData.Prop.CurTeamInventorySize = evt.size;
        }

        private void OnReceivePetPropertyChangeEventR2B(PetPropertyChangeEventR2B evt)
        {
            FormatLog("OnReceivePetPropertyChangeEventR2B", null);

            if (mPet != null)
            {
                mPet.OnRceivePropertyChangeEventR2B(evt.Order);
            }

        }

        private void OnReceivePetFollowModeChangeEventR2B(PetFollowModeChangeEventR2B evt)
        {
            FormatLog("OnReceivePetFollowModeChangeEventR2B", null);

            if (mPet != null)
            {
                mPet.OnReceivePetFollowModeChangeEventR2B(evt);
            }
        }

        


        #endregion
    }
}