context: #region License
  
  /*
   Copyright 2014 - 2015 Nikita Bernthaler
   Vladimir.cs is part of SFXVladimir.
  
   SFXVladimir is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
  
   SFXVladimir is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.
  
   You should have received a copy of the GNU General Public License
   along with SFXVladimir. If not, see <http://www.gnu.org/licenses/>.
  */
  
  #endregion License
  
  #region
  
  using System;
  using System.Collections.Generic;
  using System.Drawing;
  using System.Linq;
  using LeagueSharp;
  using LeagueSharp.Common;
  using SFXVladimir.Abstracts;
  using SFXVladimir.Args;
  using SFXVladimir.Enumerations;
  using SFXVladimir.Helpers;
  using SFXVladimir.Library;
  using SFXVladimir.Library.Logger;
  using SFXVladimir.Managers;
  using MinionManager = SFXVladimir.Library.MinionManager;
  using MinionOrderTypes = SFXVladimir.Library.MinionOrderTypes;
  using MinionTeam = SFXVladimir.Library.MinionTeam;
  using MinionTypes = SFXVladimir.Library.MinionTypes;
  using Orbwalking = SFXVladimir.SFXTargetSelector.Orbwalking;
  using Spell = SFXVladimir.Wrappers.Spell;
  using TargetSelector = SFXVladimir.SFXTargetSelector.TargetSelector;
  using Utils = SFXVladimir.Helpers.Utils;
  
  #endregion
  
  namespace SFXVladimir.Champions
  {
      internal class Vladimir : Champion
      {
          private MenuItem _eStacks;
          private Obj_AI_Minion _lastAaMinion;
          private float _lastAaMinionEndTime;
  
          protected override ItemFlags ItemFlags
          {
              get { return ItemFlags.Offensive | ItemFlags.Defensive | ItemFlags.Flee; }
          }
  
          protected override ItemUsageType ItemUsage
          {
              get { return ItemUsageType.Custom; }
          }
  
          protected override void OnLoad()
          {
              GapcloserManager.OnGapcloser += OnEnemyGapcloser;
              Drawing.OnDraw += OnDrawingDraw;
              Orbwalking.OnNonKillableMinion += OnOrbwalkingNonKillableMinion;
              Orbwalking.AfterAttack += OnOrbwalkingAfterAttack;
          }
  
          protected override void SetupSpells()
          {
              Q = new Spell(SpellSlot.Q, 600f, DamageType.Magical);
              Q.Range += GameObjects.EnemyHeroes.Select(e => e.BoundingRadius).DefaultIfEmpty(50).Min();
              Q.SetTargetted(0.25f, Q.Instance.SData.MissileSpeed);
  
              W = new Spell(SpellSlot.W, 175f, DamageType.Magical);
  
              E = new Spell(SpellSlot.E, 600f, DamageType.Magical) { Delay = 0.25f, Width = 600f };
  
              R = new Spell(SpellSlot.R, 700f, DamageType.Magical);
              R.SetSkillshot(0.25f, 175f, float.MaxValue, false, SkillshotType.SkillshotCircle);
  
              Ultimate = new UltimateManager
              {
                  Combo = true,
                  Assisted = true,
                  Auto = true,
                  Flash = false,
                  Required = true,
                  Force = true,
                  Gapcloser = false,
                  GapcloserDelay = false,
                  Interrupt = false,
                  InterruptDelay = false,
                  Spells = Spells,
                  DamageCalculation =
                      (hero, resMulti, rangeCheck) =>
                          CalcComboDamage(
                              hero, rangeCheck, Menu.Item(Menu.Name + ".combo.q").GetValue<bool>(),
                              Menu.Item(Menu.Name + ".combo.e").GetValue<bool>(), true)
              };
          }
  
          protected override void AddToMenu()
          {
              Ultimate.AddToMenu(Menu);
  
              var comboMenu = Menu.AddSubMenu(new Menu("Combo", Menu.Name + ".combo"));
              ResourceManager.AddToMenu(
                  comboMenu,
                  new ResourceManagerArgs(
                      "combo-e", ResourceType.Health, ResourceValueType.Percent, ResourceCheckType.Minimum)
                  {
                      Prefix = "E",
                      DefaultValue = 0
                  });
              comboMenu.AddItem(new MenuItem(comboMenu.Name + ".q", "Use Q").SetValue(true));
              comboMenu.AddItem(new MenuItem(comboMenu.Name + ".e", "Use E").SetValue(true));
  
              var harassMenu = Menu.AddSubMenu(new Menu("Harass", Menu.Name + ".harass"));
              ResourceManager.AddToMenu(
                  harassMenu,
                  new ResourceManagerArgs(
                      "harass-e", ResourceType.Health, ResourceValueType.Percent, ResourceCheckType.Minimum)
                  {
                      Prefix = "E",
                      DefaultValue = 30
                  });
              harassMenu.AddItem(new MenuItem(harassMenu.Name + ".q", "Use Q").SetValue(true));
              harassMenu.AddItem(new MenuItem(harassMenu.Name + ".e", "Use E").SetValue(true));
  
              var laneClearMenu = Menu.AddSubMenu(new Menu("Lane Clear", Menu.Name + ".lane-clear"));
              ResourceManager.AddToMenu(
                  laneClearMenu,
                  new ResourceManagerArgs(
                      "lane-clear-e", ResourceType.Health, ResourceValueType.Percent, ResourceCheckType.Minimum)
                  {
                      Prefix = "E",
                      DefaultValue = 45
                  });
              laneClearMenu.AddItem(new MenuItem(laneClearMenu.Name + ".q", "Use Q").SetValue(true));
              laneClearMenu.AddItem(new MenuItem(laneClearMenu.Name + ".e", "Use E").SetValue(true));
              laneClearMenu.AddItem(new MenuItem(laneClearMenu.Name + ".e-min", "E Min.").SetValue(new Slider(3, 1, 5)));
  
              var jungleClear = Menu.AddSubMenu(new Menu("Jungle Clear", Menu.Name + ".jungle-clear"));
              ResourceManager.AddToMenu(
                  jungleClear,
                  new ResourceManagerArgs(
                      "jungle-clear-e", ResourceType.Health, ResourceValueType.Percent, ResourceCheckType.Minimum)
                  {
                      Prefix = "E",
                      DefaultValue = 25
                  });
              jungleClear.AddItem(new MenuItem(jungleClear.Name + ".q", "Use Q").SetValue(true));
              jungleClear.AddItem(new MenuItem(jungleClear.Name + ".e", "Use E").SetValue(true));
  
              var lasthitMenu = Menu.AddSubMenu(new Menu("Last Hit", Menu.Name + ".lasthit"));
              lasthitMenu.AddItem(new MenuItem(lasthitMenu.Name + ".q", "Use Q").SetValue(true));
              lasthitMenu.AddItem(new MenuItem(lasthitMenu.Name + ".q-unkillable", "Q Unkillable").SetValue(true));
  
              var fleeMenu = Menu.AddSubMenu(new Menu("Flee", Menu.Name + ".flee"));
              fleeMenu.AddItem(new MenuItem(fleeMenu.Name + ".q", "Use Q").SetValue(true));
  
              var killstealMenu = Menu.AddSubMenu(new Menu("Killsteal", Menu.Name + ".killsteal"));
              killstealMenu.AddItem(new MenuItem(killstealMenu.Name + ".q", "Use Q").SetValue(true));
  
              var miscMenu = Menu.AddSubMenu(new Menu("Misc", Menu.Name + ".miscellaneous"));
  
              var wGapcloserMenu = miscMenu.AddSubMenu(new Menu("W Gapcloser", miscMenu.Name + "w-gapcloser"));
              GapcloserManager.AddToMenu(
                  wGapcloserMenu,
                  new HeroListManagerArgs("w-gapcloser")
                  {
                      IsWhitelist = false,
                      Allies = false,
                      Enemies = true,
                      DefaultValue = false,
                      Enabled = false
                  }, true);
              BestTargetOnlyManager.AddToMenu(wGapcloserMenu, "w-gapcloser");
  
              ResourceManager.AddToMenu(
                  miscMenu,
                  new ResourceManagerArgs(
                      "auto-e", ResourceType.Health, ResourceValueType.Percent, ResourceCheckType.Minimum)
                  {
                      Prefix = "E",
                      DefaultValue = 65
                  });
  
              miscMenu.AddItem(new MenuItem(miscMenu.Name + ".e-auto", "Auto E Stacking").SetValue(false));
  
              IndicatorManager.AddToMenu(DrawingManager.Menu, true);
              IndicatorManager.Add(Q);
              IndicatorManager.Add(E);
              IndicatorManager.Add(R);
              IndicatorManager.Finale();
  
              _eStacks = DrawingManager.Add("E Stacks", true);
          }
  
          private void OnOrbwalkingAfterAttack(AttackableUnit unit, AttackableUnit target)
          {
              try
              {
                  if (unit.IsMe)
                  {
                      var minion = target as Obj_AI_Minion;
                      if (minion != null)
                      {
                          _lastAaMinion = minion;
                          _lastAaMinionEndTime = Game.Time + minion.Distance(Player) / Orbwalking.GetMyProjectileSpeed() +
                                                 0.25f;
                      }
                  }
              }
              catch (Exception ex)
              {
                  Global.Logger.AddItem(new LogItem(ex));
              }
          }
  
          private void OnOrbwalkingNonKillableMinion(AttackableUnit unit)
          {
              try
              {
                  if (Orbwalker.ActiveMode == Orbwalking.OrbwalkingMode.LastHit ||
                      Orbwalker.ActiveMode == Orbwalking.OrbwalkingMode.LaneClear)
                  {
                      if (!Player.IsWindingUp && Menu.Item(Menu.Name + ".lasthit.q-unkillable").GetValue<bool>() &&
                          Q.IsReady() && Q.IsInRange(unit))
                      {
                          var target = unit as Obj_AI_Base;
                          if (target != null &&
                              (_lastAaMinion == null || target.NetworkId != _lastAaMinion.NetworkId ||
                               Game.Time > _lastAaMinionEndTime) &&
                              HealthPrediction.GetHealthPrediction(target, (int) (Q.Delay * 1000f)) > 0)
                          {
                              Q.CastOnUnit(target);
                          }
                      }
                  }
              }
              catch (Exception ex)
              {
                  Global.Logger.AddItem(new LogItem(ex));
              }
          }
  
          private void OnEnemyGapcloser(object sender, GapcloserManagerArgs args)
          {
              try
              {
                  if (args.UniqueId.Equals("w-gapcloser") && W.IsReady() &&
                      BestTargetOnlyManager.Check("w-gapcloser", W, args.Hero))
                  {
                      if (args.End.Distance(Player.Position) <= W.Range * 0.9f)
                      {
                          W.Cast(args.End);
                      }
                  }
              }
              catch (Exception ex)
              {
                  Global.Logger.AddItem(new LogItem(ex));
              }
          }
  
          protected override void OnPreUpdate() {}
  
          protected override void OnPostUpdate()
          {
              if (Orbwalker.ActiveMode == Orbwalking.OrbwalkingMode.LastHit && !Player.IsWindingUp &&
                  Menu.Item(Menu.Name + ".lasthit.q").GetValue<bool>() && Q.IsReady())
              {
                  var m =
                      MinionManager.GetMinions(Q.Range, MinionTypes.All, MinionTeam.NotAlly)
                          .FirstOrDefault(
                              e =>
                                  e.HealthPercent <= 75 &&
                                  (_lastAaMinion == null || e.NetworkId != _lastAaMinion.NetworkId ||
                                   Game.Time > _lastAaMinionEndTime) &&
                                  HealthPrediction.GetHealthPrediction(e, (int) (Q.Delay * 1000f)) < Q.GetDamage(e));
                  if (m != null)
                  {
                      Casting.TargetSkill(m, Q);
                  }
              }
  
              if (Ultimate.IsActive(UltimateModeType.Assisted) && R.IsReady())
              {
                  if (Ultimate.ShouldMove(UltimateModeType.Assisted))
                  {
                      Orbwalking.MoveTo(Game.CursorPos, Orbwalker.HoldAreaRadius);
                  }
                  var target = TargetSelector.GetTarget(R);
                  if (target != null && !RLogic(UltimateModeType.Assisted, target))
                  {
                      RLogicSingle(UltimateModeType.Assisted);
                  }
              }
  
  
gt:             if (Ultimate.IsActive(UltimateModeType.Auto) && R.IsReady())