using System;
using System.Collections.Generic;
using System.Text;
using CommonAI.Zone.Instance;
using CommonAI.Zone.Formula;
using CommonLang;
using CommonLang.Vector;

namespace CommonAI.Zone.Helper
{
    public abstract class HateSystem : IComparer<HateSystem.HateInfo>
    {
        public class HateInfo
        {
            public InstanceUnit Unit;
            public long HateValue;
			public int hitNums;				//连击数


            public HateInfo(InstanceUnit unit)
            {
                this.Unit = unit;
                this.HateValue = 0;
				this.hitNums = 0;
            }
        }

        private InstanceUnit owner;
        private TimeInterval<int> m_Timer;
        private int m_Capacity;
        protected readonly HashMap<uint, HateInfo> unitMap = new HashMap<uint, HateInfo>();
        protected readonly List<HateInfo> unitList = new List<HateInfo>(); // 第一个是仇恨值最高的

        public int Count
        {
            get { return unitList.Count; }
        }
        public int Capacity
        {
            get { return m_Capacity; }
        }
        public InstanceUnit Owner
        {
            get { return owner; }
        }

        public HateSystem(InstanceUnit owner) :
            this(owner, owner.Templates.CFG.AI_HATE_SYSTEM_CAPACITY_MS, owner.Templates.CFG.AI_NPC_CHECK_IN_GUARD_LIMIT_TIME_MS)
        {
        }
        public HateSystem(InstanceUnit owner, int capacity, int updateIntervalMS)
        {
            this.owner = owner;
            this.m_Capacity = capacity;
            this.m_Timer = new TimeInterval<int>(updateIntervalMS);
        }


        protected virtual void onTargetAdded(HateInfo target) { }
        protected virtual void onTargetRemoved(HateInfo target) { }
        protected virtual void onOwnerHitted(HateInfo attacker, AttackSource attack, int reduceHP)
        {
            attacker.HateValue += reduceHP;
        }
        
        public void OnHitted(InstanceUnit attacker, AttackSource attack, int reduceHP)
        {
            HateInfo ret = Add(attacker);
            onOwnerHitted(ret, attack, reduceHP);
            Sort();
        }

        public HateInfo Add(InstanceUnit target)
        {
            HateInfo ret;
            if (!unitMap.TryGetValue(target.ID, out ret))
            {
                ret = new HateInfo(target);
                unitMap.Add(target.ID, ret);
                unitList.Add(ret);
                onTargetAdded(ret);
            }
            return ret;
        }
        public void Remove(InstanceUnit unit)
        {
            HateInfo u = unitMap.RemoveByKey(unit.ID);
            if (u != null)
            {
                unitList.Remove(u);
                onTargetRemoved(u);
            }
        }
        public bool Contains(InstanceUnit unit)
        {
            return unitMap.ContainsKey(unit.ID);
        }
        public bool ContainsID(uint unitID)
        {
            return unitMap.ContainsKey(unitID);
        }

		public HateInfo getHateInfo(uint unitId)
		{
			return this.unitMap.Get(unitId);
		}

		public virtual void Reset()
        {
            for (int i = 0; i < unitList.Count; ++i)
            {
                HateInfo u = unitList[i];
                u.HateValue = 0;
            }
            this.Sort();
        }
        public virtual void Update(int intervalMS)
        {
			if (unitList.Count > 0 && m_Timer.Update(intervalMS))
            {
                this.Sort();
                while (unitList.Count > m_Capacity)
                {
                    int i = unitList.Count - 1;
                    HateInfo u = unitList[i];
                    unitList.RemoveAt(i);
                    unitMap.Remove(u.Unit.ID);
                    onTargetRemoved(u);
                }

                for (int i = 0; i < unitList.Count; ++i)
                {
                    HateInfo u = unitList[i];
                    if (u.Unit.Enable && u.Unit.IsActive)
                    {
                    }
                    else
                    {
                        unitList.RemoveAt(i);
                        unitMap.Remove(u.Unit.ID);
                        onTargetRemoved(u);
                        i--;
                    }
                }
            }
        }
        public virtual void Sort()
        {
            unitList.Sort(this);
        }
        public virtual void Clear()
        {
            for (int i = 0; i < unitList.Count; ++i)
            {
                HateInfo u = unitList[i];
                onTargetRemoved(u);
            }
            unitMap.Clear();
            unitList.Clear();
        }

        /// <summary>
        /// 当前首要目标
        /// </summary>
        public virtual InstanceUnit GetHated(bool onlyMonster = false)
        {
            for (int i = 0; i < unitList.Count; ++i)
            {
                HateInfo u = unitList[i];
                if (u.Unit.Enable && u.Unit.IsActive)
                {
					// 现在宠物也能拉仇恨,死亡了
                    //if(u.Unit is InstancePet)
                    //{
                    //    return (u.Unit as InstancePet).Master;
                    //}
                    //Console.WriteLine(" ------ getHated -- " + u.Unit.Name + ", " + unitList.Count + ", index = " + i);
					if(!onlyMonster || (onlyMonster && u.Unit.IsMonster))
					{
						return u.Unit;
					}                    
                }
                else
                {
                    unitList.RemoveAt(i);
                    unitMap.Remove(u.Unit.ID);
                    onTargetRemoved(u);
                    i--;
                }
            }
            return null;
        }


        /// <summary>
        /// 强制删除buff追击目标
        /// </summary>
        public virtual void forceRemoveAtkTraget() {}

        public virtual int updateHateList(float guargRangeLimit, Vector2 orginPosition)
        {
            for (int i = 0; i < unitList.Count; ++i)
            {
                HateInfo u = unitList[i];
                if (!u.Unit.Enable || !u.Unit.IsActive || !CMath.intersectRound(u.Unit.X, u.Unit.Y, u.Unit.BodyBlockSize, orginPosition.X, orginPosition.Y, guargRangeLimit))
                {
                    unitList.RemoveAt(i);
                    unitMap.Remove(u.Unit.ID);
                    onTargetRemoved(u);
                    //Console.WriteLine(" - - - - updateHateList : " + u.Unit.Name);
                    i--;
                }
            }

            return unitMap.Count;
        }

        public void print()
        {
            for (int i = 0; i < unitList.Count; ++i)
            {
                HateInfo u = unitList[i];
                Console.WriteLine(" - - - - print hate : " + u.Unit.Name);
            }
        }

		public virtual int GetHateList(List<HateInfo> ret)
        {
            int count = 0;
            for (int i = 0; i < unitList.Count; ++i)
            {
                HateInfo u = unitList[i];
                if (u.Unit.Enable && u.Unit.IsActive)
                {
					ret.Add(u);
					count++;
				}
                else
                {
                    unitList.RemoveAt(i);
                    unitMap.Remove(u.Unit.ID);
                    onTargetRemoved(u);
                    i--;
                }
            }
            return count;
        }

		public string GetHatePlayerInfo()
		{
			string hateInfo = "";
			for (int i = 0; i < unitList.Count; ++i)
			{
				if (unitList[i].Unit.IsPlayer)
				{
					hateInfo = hateInfo + "_" + unitList[i].Unit.PlayerUUID;
				}
                else
                {
                    hateInfo = hateInfo + "#" + unitList[i].Unit.Info.ID;
                }
            }

			return hateInfo;
		}

        public int getHateSize()
        {
            return unitMap.Count;
        }

        public virtual int Compare(HateSystem.HateInfo x, HateSystem.HateInfo y)
        {
            //Console.WriteLine(" - - - - x:" + x.HateValue + ", y:" + y.HateValue);
            long value = y.HateValue - x.HateValue;
			if(value != 0)
			{
				return value > 0 ? 1 : -1;
			}

			return 0;
        }
    }
}