using System.Collections.Generic;
using System.Linq;
 
using Turbo.Plugins.Default;
 
namespace Turbo.Plugins.User
{
    public class CoEPowerfullPlugin : BasePlugin, IInGameTopPainter
    {
        public bool HideWhenUiIsHidden { get; set; }
        public BuffPainter BuffPainter { get; set; }
       
        public bool bJustTheBest { get; set; }      //only max Elem
        public bool bJustAtBoss { get; set; }       //only at Boss
        public bool bDrawOnBossFeet { get; set; }   //draw on Bosses Feet if true else draw on Players Feet
        public bool bDrawCentered { get; set; }     //draw Centered
        public bool bDrawKrysbin { get; set; }      //draw KrysbinItem if Boss is "Krysbined"
		
		//position offset
		public float OffsetX { get; set; }
		public float OffsetY { get; set; }
       	
		//opacity Multiplier
		public float opacityMultiplier { get; set; }	//opacity Multiplier - single Krysbin (NOT Full Krysbin)
		public float IconSizeMultiplier { get; set; }	//IconSize Multiplier
		
        private bool inGRift { get{ return Hud.Game.SpecialArea == SpecialArea.GreaterRift; } }
        public List<HeroClass> DrawForHeroClass { get; set; }
        public HeroClass WatchThisClass { get; set; }
 
        private BuffRuleCalculator _ruleCalculator;
		private bool _init;
 
        public CoEPowerfullPlugin()
        {
            Enabled = true;
			_init = false;
           
            bJustTheBest = true;
            bJustAtBoss = true;
            bDrawOnBossFeet = true;
            bDrawCentered = true;
            bDrawKrysbin = true;
        }
 
        public override void Load(IController hud)
        {
            base.Load(hud);
 
            HideWhenUiIsHidden = false;
            BuffPainter = new BuffPainter(Hud, true)
            {
                Opacity = 1.0f,
                TimeLeftFont = Hud.Render.CreateFont("tahoma", 7, 255, 255, 255, 255, false, false, 255, 0, 0, 0, true),
            };
			
			IconSizeMultiplier = 0.65f;
            
            _ruleCalculator = new BuffRuleCalculator(Hud);
            _ruleCalculator.SizeMultiplier = 0.65f;
 
            _ruleCalculator.Rules.Add(new BuffRule(430674) { IconIndex = 1, MinimumIconCount = 0, DisableName = true }); // Arcane
            _ruleCalculator.Rules.Add(new BuffRule(430674) { IconIndex = 2, MinimumIconCount = 0, DisableName = true }); // Cold
            _ruleCalculator.Rules.Add(new BuffRule(430674) { IconIndex = 3, MinimumIconCount = 0, DisableName = true }); // Fire
            _ruleCalculator.Rules.Add(new BuffRule(430674) { IconIndex = 4, MinimumIconCount = 0, DisableName = true }); // Holy
            _ruleCalculator.Rules.Add(new BuffRule(430674) { IconIndex = 5, MinimumIconCount = 0, DisableName = true }); // Lightning
            _ruleCalculator.Rules.Add(new BuffRule(430674) { IconIndex = 6, MinimumIconCount = 0, DisableName = true }); // Physical
            _ruleCalculator.Rules.Add(new BuffRule(430674) { IconIndex = 7, MinimumIconCount = 0, DisableName = true }); // Poison
			
			OffsetX = 0f;
			OffsetY = 0f;
			opacityMultiplier = 0.35f;
           
            DrawForHeroClass = new List<HeroClass>();
            DrawForHeroClass.Add(HeroClass.Barbarian);
           
            WatchThisClass = HeroClass.Necromancer;
        }
 
        private IEnumerable<BuffRule> GetCurrentRules(HeroClass heroClass)
        {
            for (int i = 1; i <= 7; i++)
            {
                switch (heroClass)
                {
                    case HeroClass.Barbarian: if (i == 1 || i == 4 || i == 7) continue; break;
                    case HeroClass.Crusader: if (i == 1 || i == 2 || i == 7) continue; break;
                    case HeroClass.DemonHunter: if (i == 1 || i == 4 || i == 7) continue; break;
                    case HeroClass.Monk: if (i == 1 || i == 7) continue; break;
                    case HeroClass.Necromancer: if (i == 1 || i == 3 || i == 4 || i == 5) continue; break;
                    case HeroClass.WitchDoctor: if (i == 1 || i == 4 || i == 5) continue; break;
                    case HeroClass.Wizard: if (i == 4 || i == 6 || i == 7) continue; break;
                }
                yield return _ruleCalculator.Rules[i - 1];
            }
        }
		
		public bool Init()
		{
			_ruleCalculator.SizeMultiplier = IconSizeMultiplier;
			
			return true;
		}
 
        public void PaintTopInGame(ClipState clipState)
        {
			if (!_init) _init = Init();
            if (clipState != ClipState.BeforeClip) return;
            if (HideWhenUiIsHidden && Hud.Render.UiHidden) return;
            if (!inGRift) return;
           
            if (DrawForHeroClass.Any() && !DrawForHeroClass.Contains(Hud.Game.Me.HeroClassDefinition.HeroClass)) return;
           
            var bosses = Hud.Game.AliveMonsters.Where(m => m.Rarity == ActorRarity.Boss);
            if (bJustAtBoss && !bosses.Any()) return;
            IMonster boss = bosses.FirstOrDefault();
 
            foreach (var player in Hud.Game.Players.Where(p => p.HeroClassDefinition.HeroClass == WatchThisClass))
            {
                if (!player.HasValidActor) continue;
 
                var buff = player.Powers.GetBuff(430674);
                if ((buff == null) || (buff.IconCounts[0] <= 0)) continue;
 
                var classSpecificRules = GetCurrentRules(player.HeroClassDefinition.HeroClass);
 
                _ruleCalculator.CalculatePaintInfo(player, classSpecificRules);
 
                if (_ruleCalculator.PaintInfoList.Count == 0) return;
                if (!_ruleCalculator.PaintInfoList.Any(info => info.TimeLeft > 0)) return;
 
                var highestElementalBonus = player.Offense.HighestElementalDamageBonus;
 
                for (int i = 0; i < _ruleCalculator.PaintInfoList.Count; i++)
                {
                    var info = _ruleCalculator.PaintInfoList[0];
                    if (info.TimeLeft <= 0)
                    {
                        _ruleCalculator.PaintInfoList.RemoveAt(0);
                        _ruleCalculator.PaintInfoList.Add(info);
                    }
                    else break;
                }
               
                var _indexBest = 0;
               
                for (int orderIndex = 0; orderIndex < _ruleCalculator.PaintInfoList.Count; orderIndex++)
                {
                    var info = _ruleCalculator.PaintInfoList[orderIndex];
                    var best = false;
                    switch (info.Rule.IconIndex)
                    {
                        case 1: best = player.Offense.BonusToArcane == highestElementalBonus; break;
                        case 2: best = player.Offense.BonusToCold == highestElementalBonus; break;
                        case 3: best = player.Offense.BonusToFire == highestElementalBonus; break;
                        case 4: best = player.Offense.BonusToHoly == highestElementalBonus; break;
                        case 5: best = player.Offense.BonusToLightning == highestElementalBonus; break;
                        case 6: best = player.Offense.BonusToPhysical == highestElementalBonus; break;
                        case 7: best = player.Offense.BonusToPoison == highestElementalBonus; break;
                    }
                    if (best && !bJustTheBest) info.Size *= 1.35f;
                    if (best && orderIndex > 0)
                    {
                        _indexBest = orderIndex;
                        info.TimeLeft = (orderIndex - 1) * 4 + _ruleCalculator.PaintInfoList[0].TimeLeft;
                    }
                    else info.TimeLeftNumbersOverride = false;
                }
               
                //remove all but best
                if (bJustTheBest)
                {
                    var _tmp = _ruleCalculator.PaintInfoList[_indexBest];
                    _ruleCalculator.PaintInfoList.Clear();
                    _ruleCalculator.PaintInfoList.Add(_tmp);
                }
               
                //get drawing Coordinates
                IScreenCoordinate _sc;
                if (bDrawOnBossFeet)
                {
                    if (boss == null) return;
                    _sc = boss.FloorCoordinate.ToScreenCoordinate();
                }
                else
                    _sc = player.FloorCoordinate.ToScreenCoordinate();
               
               
                bool _kDrawn = false;
                if (bDrawKrysbin)   //paint Krysbin
                    _kDrawn = DrawKrysbinInBossfight(player, boss, _sc);
               
                //paint CoE
				if (bDrawCentered)
					BuffPainter.PaintHorizontalCenter(_ruleCalculator.PaintInfoList, _sc.X - (_kDrawn ? _ruleCalculator.StandardIconSize/2 : 0) + OffsetX, _sc.Y + OffsetY, 0, _ruleCalculator.StandardIconSize, 0);
				else
					BuffPainter.PaintHorizontal(_ruleCalculator.PaintInfoList, _sc.X + OffsetX, _sc.Y + OffsetY, _ruleCalculator.StandardIconSize, 0);
               
            }
        }
       
        private bool DrawKrysbinInBossfight(IPlayer player, IMonster boss, IScreenCoordinate sc)
        {
            if (WatchThisClass != HeroClass.Necromancer) return false;      //watch = necro !!
            if (boss == null) return false;                                 //no boss
            var StateKrysbin = isKrysbin(boss);
			if (StateKrysbin == 0) return false;							//no krysbin_debuff
           
            IBuff _bKrysbin = player.Powers.GetBuff(475241);    //getbuff wegen cube    // Sno: 475241
            if (_bKrysbin == null || !_bKrysbin.Active) return false;       //no krysbin in use
           
            uint itemSno = 1236308205;                          //1236308205 - KrysbinsSentence_ItemSno
            var snoItem = Hud.Inventory.GetSnoItem(itemSno);
           
           
            //buff position
            var _x = sc.X;
            float totalWidth = 0f;
            foreach (var info in _ruleCalculator.PaintInfoList)
                totalWidth += info.Size;
            if (bDrawCentered)
                _x += totalWidth / 2 - _ruleCalculator.StandardIconSize/2;
            else
                _x += totalWidth;
           
            var itemRect = new System.Drawing.RectangleF(_x + OffsetX, sc.Y + OffsetY, _ruleCalculator.StandardIconSize, _ruleCalculator.StandardIconSize);
           
		    //buff strenght -> opacity
			float opacity = StateKrysbin == 1 ? opacityMultiplier : 1.0f;
		   
            var slotTexture = Hud.Texture.InventorySlotTexture;
            slotTexture.Draw(itemRect.X, itemRect.Y, itemRect.Width, itemRect.Height, opacity);
           
            var backgroundTexture = Hud.Texture.InventoryLegendaryBackgroundSmall;
            backgroundTexture.Draw(itemRect.X, itemRect.Y, itemRect.Width, itemRect.Height, opacity);
           
            var itemTexture = Hud.Texture.GetItemTexture(snoItem);
            if (itemTexture != null)
            {
                itemTexture.Draw(itemRect.X, itemRect.Y, itemRect.Width, itemRect.Height, opacity);
            }
           
            return true;
        }
       
        private uint isKrysbin(IMonster elite)
		{
			if (elite.Frozen || elite.Stunned || elite.Blind)
				return 2;
			if (elite.Slow || elite.Chilled)
				return 1;
			
			return 0;
		}
 
    }
 
}