context: using System;
  using System.Collections.Generic;
  using System.Linq;
  using DZAIO_Reborn.Core;
  using DZAIO_Reborn.Helpers;
  using DZAIO_Reborn.Helpers.Modules;
  using DZAIO_Reborn.Helpers.Positioning;
  using DZAIO_Reborn.Plugins.Champions.Bard.Modules;
  using DZAIO_Reborn.Plugins.Interface;
  using DZLib.Core;
  using DZLib.Menu;
  using DZLib.MenuExtensions;
  using LeagueSharp;
  using LeagueSharp.Common;
  using SharpDX;
  
  using EloBuddy; 
   using LeagueSharp.Common; 
   namespace DZAIO_Reborn.Plugins.Champions.Bard
  {
      class Bard : IChampion
      {
          public static int TunnelObjectNetworkID;
          public static Vector3 TunnelEntrancePosition = Vector3.Zero;
          public static Vector3 TunnelExitPosition = Vector3.Zero;
  
          public void OnLoad(Menu menu)
          {
              var comboMenu = new Menu(ObjectManager.Player.ChampionName + ": Combo", "dzaio.champion.bard.combo");
              {
                  comboMenu.AddModeMenu(ModesMenuExtensions.Mode.Combo, new[] { SpellSlot.Q, SpellSlot.R }, new[] { true, true });
                  comboMenu.AddSlider("dzaio.champion.bard.combo.r.min", "Min Enemies for R", 2, 1, 5);
  
                  menu.AddSubMenu(comboMenu);
              }
  
              var mixedMenu = new Menu(ObjectManager.Player.ChampionName + ": Mixed", "dzaio.champion.bard.harrass");
              {
                  mixedMenu.AddModeMenu(ModesMenuExtensions.Mode.Harrass, new[] { SpellSlot.Q}, new[] { true });
                  mixedMenu.AddSlider("dzaio.champion.bard.mixed.mana", "Min Mana % for Harass", 30, 0, 100);
                  menu.AddSubMenu(mixedMenu);
              }
  
              var extraMenu = new Menu(ObjectManager.Player.ChampionName + ": Extra", "dzaio.champion.bard.extra");
              {
                  extraMenu.AddBool("dzaio.champion.bard.extra.interrupter", "Interrupter (Q)", true);
                  extraMenu.AddBool("dzaio.champion.bard.extra.antigapcloser", "Antigapcloser (Q)", true);
                  extraMenu.AddBool("dzaio.champion.bard.extra.autoQ", "Auto Q Stunned / Rooted", true);
                  extraMenu.AddBool("dzaio.champion.bard.extra.autoQKS", "Auto Q KS", true);
                  extraMenu.AddBool("dzaio.champion.bard.extra.supportmode", "Support Mode", true);
                  extraMenu.AddKeybind("dzaio.champion.bard.extra.fleemode", "Flee Mode", new Tuple<uint, KeyBindType>('Z', KeyBindType.Press));
              }
  
              Variables.Spells[SpellSlot.Q].SetSkillshot(0.25f, 100, 1600, false, SkillshotType.SkillshotLine);
              Variables.Spells[SpellSlot.E].SetSkillshot(0.25f, 60, 1200, true, SkillshotType.SkillshotLine);
          }
  
          public void RegisterEvents()
          {
              DZInterrupter.OnInterruptableTarget += OnInterrupter;
              DZAntigapcloser.OnEnemyGapcloser += OnGapcloser;
              Orbwalking.BeforeAttack += BeforeAttack;
              GameObject.OnCreate += OnCreateObject;
              GameObject.OnDelete += OnDeleteObject;
          }
  
          private void OnCreateObject(GameObject sender, System.EventArgs args)
          {
              if (sender.Name.Contains("BardDoor_EntranceMinion"))
              {
                  TunnelObjectNetworkID = sender.NetworkId;
                  TunnelEntrancePosition = sender.Position;
              }
  
              if (sender.Name.Contains("BardDoor_ExitMinion"))
              {
                  TunnelExitPosition = sender.Position;
              }
          }
  
          private void OnDeleteObject(GameObject sender, System.EventArgs args)
          {
              if (sender.Name.Contains("BardDoor_EntranceMinion") && sender.NetworkId == TunnelObjectNetworkID)
              {
                  TunnelObjectNetworkID = -1;
                  TunnelEntrancePosition = Vector3.Zero;
                  TunnelExitPosition = Vector3.Zero;
              }
          }
  
          private void BeforeAttack(Orbwalking.BeforeAttackEventArgs args)
          {
  
              if (args.Target.Type == GameObjectType.obj_AI_Minion
              && (Variables.Orbwalker.ActiveMode == Orbwalking.OrbwalkingMode.Mixed)
              && Variables.AssemblyMenu.GetItemValue<bool>("dzaio.champion.bard.extra.supportmode"))
              {
                  if (ObjectManager.Player.CountAlliesInRange(Variables.AssemblyMenu.GetItemValue<Slider>("dz191.bard.misc.attackMinionRange").Value) > 0)
                  {
                      args.Process = false;
                  }
              }
          }
  
          private void OnGapcloser(DZLib.Core.ActiveGapcloser gapcloser)
          {
              if (Variables.AssemblyMenu.GetItemValue<bool>("dzaio.champion.bard.extra.antigapcloser") 
                  && Variables.Spells[SpellSlot.Q].IsReady()
                  && gapcloser.Sender.IsValidTarget()
                  && gapcloser.End.Distance(ObjectManager.Player.ServerPosition) < gapcloser.Start.Distance(ObjectManager.Player.ServerPosition))
              {
                  HandleQ(gapcloser.Sender);
              }
          }
  
          private void OnInterrupter(AIHeroClient sender, DZInterrupter.InterruptableTargetEventArgs args)
          {
              if (Variables.AssemblyMenu.GetItemValue<bool>("dzaio.champion.bard.extra.interrupter") 
                  && Variables.Spells[SpellSlot.Q].IsReady()
                  && sender.IsValidTarget()
                  && args.DangerLevel >= DZInterrupter.DangerLevel.High)
              {
                  HandleQ(sender);
              }
          }
  
          public Dictionary<SpellSlot, Spell> GetSpells()
          {
              return new Dictionary<SpellSlot, Spell>
                        {
                              {SpellSlot.Q, new Spell(SpellSlot.Q, 950f)},
                              {SpellSlot.W, new Spell(SpellSlot.W, 945f)},
                              {SpellSlot.E, new Spell(SpellSlot.E, float.MaxValue)}
                        };
          }
  
          public List<IModule> GetModules()
          {
              return new List<IModule>()
              {
                  new BardAutoQ()
              };
          }
  
          public void OnTick()
          {
              if (Variables.AssemblyMenu.GetItemValue<KeyBind>("dzaio.champion.bard.extra.fleemode").Active)
              {
                  DoFlee();
              }
          }
  
          private void DoFlee()
          {
              if (!Variables.Spells[SpellSlot.E].IsReady() || TunnelObjectNetworkID == -1)
              {
                  Orbwalking.MoveTo(Game.CursorPos);
              }
  
              if (PositioningHelper.DoPositionsCrossWall(ObjectManager.Player.ServerPosition, Game.CursorPos)
                  && PositioningHelper.GetWallLength(ObjectManager.Player.ServerPosition,Game.CursorPos) >= 200f)
              {
                  Orbwalking.MoveTo(PositioningHelper.GetFirstWallPoint(ObjectManager.Player.ServerPosition, Game.CursorPos));
              }
  
              //Q
  
              var ComboTarget = TargetSelector.GetTarget(Variables.Spells[SpellSlot.Q].Range / 1.3f, TargetSelector.DamageType.Magical);
  
              if (Variables.Spells[SpellSlot.Q].IsReady() && ComboTarget.IsValidTarget())
              {
                  HandleQ(ComboTarget);
              }
  
              //E
  
              var dir = ObjectManager.Player.ServerPosition.To2D() + ObjectManager.Player.Direction.To2D().Perpendicular() * (ObjectManager.Player.BoundingRadius * 2.5f);
              var Extended = Game.CursorPos;
  
              if (dir.IsWall() 
                   && PositioningHelper.GetWallLength(ObjectManager.Player.ServerPosition, Extended) >= 200f 
                   && PositioningHelper.DoPositionsCrossWall(ObjectManager.Player.ServerPosition, Extended))
              {
                   Variables.Spells[SpellSlot.E].Cast(Extended);
              }
          }
  
          public void OnCombo()
          {
              var ComboTarget = TargetSelector.GetTarget(Variables.Spells[SpellSlot.Q].Range / 1.3f, TargetSelector.DamageType.Magical);
  
              if (Variables.Spells[SpellSlot.Q].IsEnabledAndReady(ModesMenuExtensions.Mode.Combo) && ComboTarget.IsValidTarget())
              {
                  HandleQ(ComboTarget);
              }
  
              if (Variables.Spells[SpellSlot.W].IsEnabledAndReady(ModesMenuExtensions.Mode.Combo))
              {
                  HandleW();
              }
          }
  
          public void OnMixed()
          {
              var ComboTarget = TargetSelector.GetTarget(Variables.Spells[SpellSlot.Q].Range / 1.3f, TargetSelector.DamageType.Magical);
  
              if (Variables.Spells[SpellSlot.Q].IsEnabledAndReady(ModesMenuExtensions.Mode.Harrass) && ComboTarget.IsValidTarget())
              {
                  HandleQ(ComboTarget);
              }
  
              if (Variables.Spells[SpellSlot.W].IsEnabledAndReady(ModesMenuExtensions.Mode.Harrass))
              {
                  HandleW();
              }
          }
  
          public void OnLastHit()
          { }
  
          public void OnLaneclear()
          {
  
          }
          private static void HandleW()
          {
              var HealthPercent = 30f;
  
              if (ObjectManager.Player.IsRecalling() || ObjectManager.Player.InShop() || !Variables.Spells[SpellSlot.W].IsReady())
              {
                  return;
              }
  
              if (ObjectManager.Player.HealthPercent <= HealthPercent)
              {
                  var castPosition = ObjectManager.Player.ServerPosition.Extend(Game.CursorPos, ObjectManager.Player.BoundingRadius * 1.3f);
                  Variables.Spells[SpellSlot.W].Cast(castPosition);
                  return;
              }
  
              var LHAlly = HeroManager.Allies
                  .Where(ally => ally.IsValidTarget(Variables.Spells[SpellSlot.W].Range, false)
  
gt:                     && ally.HealthPercent <= HealthPercent