using CommonAI.Zone.Instance;
using CommonAI.Zone.ZoneEditor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XmdsCommon.Plugin;
using CommonAI.Zone;
using CommonAI.Zone.Attributes;
using CommonAI.Zone.Helper;
using XmdsCommonServer.Plugin.Units;
using XmdsCommonServer.Plugin.Quest;
using XmdsCommon.EditorData;
using CommonLang;
using CommonLang.Vector;
using CommonAI.RTS.Manhattan;
using XmdsCommon.Message;
using CommonAI.Data;
using CommonAI.ZoneServer.JSGModule;

namespace XmdsCommonServer.Plugin.Scene
{
    /// <summary>
    /// Xmds场景
    /// </summary>
    public class XmdsServerScene : EditorScene
    {
        /// <summary>
        /// 遍历单位
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="cancel">设置为True,立即停止遍历</param>
        public delegate void ObjectForEachAction<T>(T obj, ref bool cancel) where T : class;

        private HashMap<int, List<ZoneRegion>> mRebirthRegionMap = new HashMap<int, List<ZoneRegion>>();

        public XmdsServerScene(TemplateManager templates, InstanceZoneListener listener, SceneData data, GSCreateAreaData gsData, string bindGameSrvId, int spaceDiv = 11)
            : this(templates, listener, data, gsData, spaceDiv, DateTime.Now.Millisecond, bindGameSrvId)
        { }
        protected XmdsServerScene(TemplateManager templates, InstanceZoneListener listener, SceneData data, GSCreateAreaData gsData, int spaceDiv, int rarndomSeed, string bindGameSrvId)
            : base(templates, listener, data, gsData, spaceDiv, rarndomSeed)
        {
            this.OnQuestAccepted += XmdsServerScene_OnQuestAccepted;
            this.OnQuestDropped += XmdsServerScene_OnQuestDropped;
            this.OnQuestCommitted += XmdsServerScene_OnQuestCommitted;
            this.OnQuestStatusChanged += XmdsServerScene_OnQuestStatusChanged;
            this.OnPlayerReady += XmdsServerScene_OnPlayerReady;

			//设置山大王信息
			this.mKingID = XmdsDataMgr.GetInstance().GetMapKingID(this.GetSceneID());
			this.mBindGameSrvId = bindGameSrvId;

		}
		protected override void InitTerrain(SceneData data, int spaceDiv, out ZoneManhattanMap terrain_data, out AstarManhattan path_finder, out ManhattanMapAreaGenerator area_gen)
        {
            if ((data.Properties as XmdsSceneProperties).ServerSceneData.UsespaceDiv) { spaceDiv = 11; }
            else { spaceDiv = 0; }
            base.InitTerrain(data, spaceDiv, out terrain_data, out path_finder, out area_gen);
        }
        //         private static int GetSpaceDiv(SceneData data)
        //         {
        //             if ((data.Properties as XmdsSceneProperties).ServerSceneData.UsespaceDiv) { return 11; }
        //             else { return 0; }
        //         }


        //---------------------------------------------------------------------------------------------------------------------
        #region _任务相关_
        private void XmdsServerScene_OnPlayerReady(InstancePlayer player)
        {
            XmdsInstancePlayer p = player as XmdsInstancePlayer;
            var list = p.GetQuests();
            foreach (var q in list)
            {
                QuestScriptManager.CreateQuestScript(q.QuestID, p);
            }
        }

        private void XmdsServerScene_OnQuestStatusChanged(InstancePlayer player, string quest, string key, string value)
        {
            if (key == XmdsQuestData.Attribute_InitOK)
            {
                QuestScriptManager.CreateQuestScript(quest, player as XmdsInstancePlayer);
            }
            else
            {
                QuestScriptManager.QuestStatusChanged(quest, player as XmdsInstancePlayer, key, value);
            }

        }
        private void XmdsServerScene_OnQuestAccepted(InstancePlayer player, string quest)
        {
            //此时没有属性,CreateQuestScript放在INIT_OK
            //QuestScriptManager.CreateQuestScript(quest, player as XmdsInstancePlayer);
        }
        private void XmdsServerScene_OnQuestCommitted(InstancePlayer player, string quest)
        {
            QuestScriptManager.ClearQuestScript(quest, player as XmdsInstancePlayer);
        }
        private void XmdsServerScene_OnQuestDropped(InstancePlayer player, string quest)
        {
            QuestScriptManager.ClearQuestScript(quest, player as XmdsInstancePlayer);
        }

        #endregion
        //---------------------------------------------------------------------------------------------------------------------
        #region _AOI_相关_

        public override bool IsTeammates(InstanceUnit src, InstanceUnit dst)
        {
            if (src != null && dst != null)
            {
                var s_v = src.Virtual as XmdsVirtual;
                var d_v = dst.Virtual as XmdsVirtual;
                return d_v.IsTeamMember(s_v.GetPlayerUUID());
            }
            return false;
        }

        public override bool IsVisibleAOI(InstanceZoneObject src, InstanceZoneObject dst)
        {
            if (src is XmdsInstancePlayer)
            {
				XmdsInstancePlayer player = src as XmdsInstancePlayer;
                if (!player.IsPlayerReady())
                {
                    return false;
                }

				String bindPlayerId = dst.GetBindPlayerId();
				if(bindPlayerId != null && bindPlayerId != player.PlayerUUID)
				{
					return false;
				}
            }
			
            if (src.AoiStatus == dst.AoiStatus)
            {
                var dstUnit = dst as InstanceUnit;
                if (dstUnit == null)
                {
                    return true;
                }

				//if(dstUnit.IsPet)
				//{
				//	InstancePet dstPet = dst as InstancePet;
				//	if(dstPet != null && dstPet.Master != null && dstPet.Master.AoiStatus != src.AoiStatus)
				//	{
				//		return false;
				//	}
				//}

				if (dstUnit.IsVisible)
				{
					return true;
				}

                if (IsTeammates(src as InstanceUnit, dstUnit))
                {
                    return (dstUnit.Virtual as XmdsVirtual).TeamMemberVisible;
                }
                return false;
            }
			//else
			//{
			//	InstancePet dstPet = dst as InstancePet;
			//	if (dstPet != null && dstPet.Master != null && dstPet.Master == src)
			//	{
			//		return true;
			//	}
			//}

            return base.IsVisibleAOI(src, dst);
        }

        #endregion

        #region Attack.

        public override bool IsAttackable(InstanceUnit src, InstanceUnit target, SkillTemplate.CastTarget expectTarget, AttackReason reason, ITemplateData weapon)
        {
			// 宠物也能被攻击
            //if (target is InstancePet)
            //{
            //    return false;
            //}

            var sp = (src.Virtual as XmdsVirtual);
            if (sp == null)
            {
                Log.Error("IsAttackable src or src.Virtual is null");
                return false;
            }

            var dp = (target.Virtual as XmdsVirtual);
            if (dp == null)
            {
                Log.Error("IsAttackable target or target.Virtual is null");
                return false;
            }

			#region 安全区域检测. 宠物不会是目标
			if (expectTarget == SkillTemplate.CastTarget.Enemy && target.IsPlayerUnit && src.IsPlayerUnit)
			{
				if (target.Virtual.IsInSafeArea() || src.Virtual.IsInSafeArea())
				{
					return false;
				}
			}

			#endregion

			#region 中立单位检测.

			if (target.Force == 0)  //0代表绝对中立.不能被攻击.
            {
                return false;
            }

            #endregion

            #region 无敌单位.


            if (target.IsInvincible && expectTarget == SkillTemplate.CastTarget.Enemy)
            {
                return false;
            }

			//追杀怪只能追杀目标
			if (!String.IsNullOrEmpty(src.GetAttackPlayer()))
			{
				if(target.PlayerUUID == null || target.PlayerUUID != src.GetAttackPlayer())
				{
					return false;
				}
			}

			
			if (src != target && (!src.IsPlayerUnit || !JSGModule.IsExpectValidForPet(expectTarget)))
			{
				// 宠物攻击的时候
				if (src.IsPet)
				{
					// 目标是宠物或者非主人
					if (target.IsPet || (target.IsPlayer && src.Virtual.GetMasterID() != target.ID))
					{
						return false;
					}
				}
				// 宠物被攻击的时候
				else if (target.IsPet)
				{
					// 攻击者是宠物或者非主人
					//if (src.IsPet || (src.IsPlayer && target.Virtual.GetMasterID() != src.ID))
					{
						return false;
					}
				}								
			}

			//被追杀人和怪 可攻击追杀怪
			if(!String.IsNullOrEmpty(target.GetAttackPlayer()) && src.PlayerUUID != target.GetAttackPlayer())
			{
				if (src.IsPet && src.Virtual.GetMasterUnit() != null)
				{
					if (src.Virtual.GetMasterUnit().PlayerUUID != target.GetAttackPlayer())
					{
						return false;
					}
				}
				else
				{
					return false;
				}				
			}

			#endregion

			#region 隐形对攻击的影响.

			//单位隐形时,需要判断搜索方是否为其队友,如果是则无视隐形,否按照攻击逻辑判断.
			//if(target.IsDead)
			//if (target.IsVisible == false)
   //         {
   //             if ((reason == AttackReason.Tracing || reason == AttackReason.Look) &&
   //                  expectTarget == SkillTemplate.CastTarget.Enemy)
   //             {
   //                 bool attackAble = false;

   //                 var zv = ((target as InstanceUnit).Virtual as XmdsVirtual);

   //                 if (zv.TeamMemberVisible)
   //                 {
   //                     //不是队友看不到单位,搜索时不可见.
   //                     var uuid = ((target as InstanceUnit).Virtual as XmdsVirtual).GetPlayerUUID();
			//			attackAble = !((src as InstanceUnit).Virtual as XmdsVirtual).IsTeamMember(uuid);
   //                 }

   //                 return attackAble;
   //             }

   //         }

            #endregion

            #region 位面检测.

            //隐身状态下,同位面,不可见,但可以被攻击.
            if (reason != AttackReason.Attack && !IsVisibleAOI(src, target))//AOI相关.不在同位面.
            {
                //非攻击性质才算AOI.
                return false;
            }

            #endregion

            #region PK等级保护.

            if (((target.Virtual) as XmdsVirtual).IsAttackable(src.Virtual as XmdsVirtual) == false)
            {
                return false;
            }

            #endregion


            #region 技能目标单位类型状态检测.

            //攻击作用单位类型.
            var unit_type = XmdsSkillProperties.TargetUnitType.ALL;
            if (weapon is SkillTemplate && reason == AttackReason.Attack)
            {
                unit_type = ((weapon as SkillTemplate).Properties as XmdsSkillProperties).NeedTargetType;
            }
            else if (weapon is SpellTemplate && reason == AttackReason.Attack)
            {
                unit_type = ((weapon as SpellTemplate).Properties as XmdsSpellProperties).NeedTargetType;
            }
            switch (unit_type)
            {
                case XmdsSkillProperties.TargetUnitType.Monster:
                    if (!(dp is XmdsVirtual_Monster))
                    {
                        return false;
                    }
                    break;
                case XmdsSkillProperties.TargetUnitType.Player:
                    if (!(dp is XmdsVirtual_Player))
                    {
                        return false;
                    }
                    break;
                case XmdsSkillProperties.TargetUnitType.ExcpetPlayer:
                    if ((dp is XmdsVirtual_Player))
                    {
                        return false;
                    }
                    break;
            }

            bool onlyForDead = false;
            //对死人.
            if (src.CurrentState != null)
            {
                InstanceUnit.State s = src.CurrentState;
                InstanceUnit.StateSkill ss = s as InstanceUnit.StateSkill;
                if (ss != null)
                {
                    if ((ss.SkillData.Properties as XmdsSkillProperties).TargetType == XmdsSkillProperties.XmdsSkillTargetType.AllianceDead)
                    {
                        //只对死亡单位有效.
                        onlyForDead = true;
                    }
                }
            }

            if (!target.IsActive)
            {
                if (onlyForDead)
                {
                    /*
                    switch(expectTarget)
                    {
                        case SkillTemplate.CastTarget.Alias:
                        case SkillTemplate.CastTarget.AlliesExcludeSelf:
                            return (src.Virtual as XmdsVirtual).IsTeamMember((target.Virtual as XmdsVirtual).GetPlayerUUID());
                    }
                    */

                    //只要是玩家,不管敌友,都可以复活.
                    return (target is XmdsInstancePlayer);

                }
                return false;
            }
            else
            {

                //对活人.
                if (onlyForDead == false)
                {
                    switch (expectTarget)
                    {
                        case SkillTemplate.CastTarget.Enemy:
                            //不是自己人.
                            return !(src.Virtual as XmdsVirtual).IsAllies((target.Virtual as XmdsVirtual), expectTarget, reason);
                        case SkillTemplate.CastTarget.PetForMaster:
                            //if (src.Virtual is XmdsVirtual_Pet)
                            //{
                            //    if ((src.Virtual as XmdsVirtual_Pet).IsMaster((target.Virtual as XmdsVirtual)))
                            //        return true;
                            //}
							if(src is InstancePet)
							{
								InstancePet pet = src as InstancePet;
								if(pet != null && pet.Master == target)
								{
									return true;
								}
							}
                            return false;
                        case SkillTemplate.CastTarget.EveryOne:
							return JudgeEveryOneAttackable(src, target, expectTarget);
						case SkillTemplate.CastTarget.Alias:
                        case SkillTemplate.CastTarget.AlliesExcludeSelf:
                            // 可能存在即使队友,又是敌人的,所以如果是敌人就不认队友了,你tmd和我为敌,我就不给你加血
                            if (!(src.Virtual as XmdsVirtual).IsAllies((target.Virtual as XmdsVirtual), expectTarget, reason))
                                return false;
                            if (src == target) { return false; }
                            return (src.Virtual as XmdsVirtual).IsTeamMember(target);
                        case SkillTemplate.CastTarget.AlliesIncludeSelf:
                            // 可能存在即使队友,又是敌人的,所以如果是敌人就不认队友了,你tmd和我为敌,我就不给你加血
                            if (!(src.Virtual as XmdsVirtual).IsAllies((target.Virtual as XmdsVirtual), expectTarget, reason))
                                return false;
                            return (src.Virtual as XmdsVirtual).IsTeamMember(target);
                        //return (src.Virtual as XmdsVirtual).IsTeamMember((target.Virtual as XmdsVirtual).GetPlayerUUID());
                        case SkillTemplate.CastTarget.EveryOneExcludeSelf:
							return JudgeEveryOneAttackable(src, target, expectTarget);
						case SkillTemplate.CastTarget.Self:
                            return src == target;
						case SkillTemplate.CastTarget.EnemyAndSelf:
							return src == target || !(src.Virtual as XmdsVirtual).IsAllies((target.Virtual as XmdsVirtual), expectTarget, reason);
						case SkillTemplate.CastTarget.NA:
                        default:
                            return false;
                    }
                }

                return false;
            }

            #endregion

        }

		/** 判断所有人类型可攻击模式 */
		private bool JudgeEveryOneAttackable(InstanceUnit src, InstanceUnit target, SkillTemplate.CastTarget expectTarget)
		{
			//if (SkillTemplate.CastTarget.EveryOne == expectTarget)
			//{
			//	return (!target.IsInvincible);
			//}
			//else if (SkillTemplate.CastTarget.EveryOneExcludeSelf == expectTarget)
			//{
			//	return (src != target) && (!target.IsInvincible);
			//}

			if (SkillTemplate.CastTarget.EveryOneExcludeSelf == expectTarget && src == target)
			{
				return false;
			}

			switch (src.Virtual.GetCurPKMode())
			{
				case PKMode.Peace://和平模式使用默认出生的force.	
					if (src.Virtual.GetForceID() == target.Virtual.GetForceID())
					{
						return src.Virtual.IsAllies(target.Virtual, true, true);
					}
					return true;
				case PKMode.force://阵营模式使用Camp.
					if (src.Virtual.GetForceID() == target.Virtual.GetForceID())
					{
						return false;
					}
					return !src.Virtual.IsAllies(target.Virtual, true, true);
				case PKMode.Guild:
					if (src.Virtual.IsGuildMember(target.Virtual.GetGuildID()))
					{
						return false;
					}
					return !src.Virtual.IsAllies(target.Virtual, true, true);
				case PKMode.Team:
					return !src.Virtual.IsAllies(target.Virtual, true, true);
				case PKMode.All:
					return !(src == target);
				case PKMode.Justice:
					if (target.Virtual.GetCurPKLevel() == PKLevel.White)
					{
						return false;
					}

					return !src.Virtual.IsAllies(target.Virtual, true, true); ;
				case PKMode.Server:
					if (src.Virtual.IsServerMember(target.Virtual.GetServerID()))
					{
						return false;
					}
					return !src.Virtual.IsAllies(target.Virtual, true, true); ;
			}

			return false;
		}


        #endregion

        #region Region相关.

        protected override void InitEditRegion(RegionData rdata)
        {
            base.InitEditRegion(rdata);

            //单位复活点.
            ZoneRegion flag = getFlag(rdata.Name) as ZoneRegion;
            if (flag != null && rdata.Abilities != null)
            {
                List<ZoneRegion> temp = null;

                foreach (AbilityData td in rdata.Abilities)
                {
                    if (td is XmdsRebirthAbility)
                    {
                        XmdsRebirthAbility zra = td as XmdsRebirthAbility;

                        if (mRebirthRegionMap.TryGetValue(zra.START_Force, out temp))
                        {
                            temp.Add(flag);
                        }
                        else
                        {
                            temp = new List<ZoneRegion>();
                            temp.Add(flag);
                            mRebirthRegionMap.Add(zra.START_Force, temp);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 遍历所有复活点
        /// </summary>
        /// <param name="force"></param>
        /// <param name="action"></param>
        public void ForEachRebirthRegion(int force, Action<ZoneRegion> action)
        {
            List<ZoneRegion> temp = null;

            if (mRebirthRegionMap.TryGetValue(force, out temp))
            {
                for (int i = temp.Count - 1; i >= 0; --i)
                {
                    var rg = temp[i];
                    action(rg);
                }
            }
        }

        /// <summary>
        /// 获得最近的复活点
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="regionForce"></param>
        /// <returns></returns>
        public ZoneRegion GetNearestRebirthRegion(float x, float y, int regionForce)
        {
            using (var list = ListObjectPool<ZoneRegion>.AllocAutoRelease())
            {
                ZoneRegion ret = null;
                float min_value = float.MaxValue;
                float len;

                this.ForEachRebirthRegion(regionForce, (rg) =>
                {
                    if (rg.Enable)
                    {
                        len = MathVector.getDistanceSquare(x, y, rg.X, rg.Y);
                        if (len < min_value)
                        {
                            min_value = len;
                            ret = rg;
                        }
                    }
                });

                return ret;
            }
        }

        /// <summary>
        /// 获得该地图随机的复活点
        /// </summary>
        /// <param name="regionForce"></param>
        /// <returns></returns>
        public ZoneRegion GetRandomRebirthRegion(int regionForce)
        {
            using (var list = ListObjectPool<ZoneRegion>.AllocAutoRelease())
            {
                ZoneRegion ret = null;

                List<ZoneRegion> temp = null;
                mRebirthRegionMap.TryGetValue(regionForce, out temp);
                //不知道阵营的情况下,用这个逻辑
                if(temp == null)
                {
                    mRebirthRegionMap.TryGetValue(-1, out temp);
                }

                if (temp != null)
                {
                    int num = RandomN.Next(0, temp.Count);

                    if (num > temp.Count)
                    {
                        num = temp.Count - 1;
                    }

                    return temp[num];
                }

                return ret;
            }
        }

        /// <summary>
        /// 获得场景下对应阵营的出生点.
        /// </summary>
        /// <param name="startForce"></param>
        /// <returns></returns>
        public List<ZoneRegion> GetRebirthRegions(byte startForce)
        {
            List<ZoneRegion> ret = null;

            if (mRebirthRegionMap != null)
            {
                mRebirthRegionMap.TryGetValue(startForce, out ret);
            }

            return ret;
        }

        #endregion

        #region Events

        internal void callback_OnCombatStateChange(InstanceUnit unit, BattleStatus status)
        {
            if (mOnCombatStateChange != null)
            {
                mOnCombatStateChange.Invoke(unit, status);
            }
        }

        public delegate void CombatStateChangeHandler(InstanceUnit unit, BattleStatus status);

        [EventTriggerDescAttribute("单位战斗状态改变")]
        public event CombatStateChangeHandler OnCombatStateChange { add { mOnCombatStateChange += value; } remove { mOnCombatStateChange -= value; } }

        private CombatStateChangeHandler mOnCombatStateChange;

        protected override void ClearEvents()
        {
            mOnCombatStateChange = null;
            base.ClearEvents();
        }
        #endregion
    }
}