using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using GTANetworkAPI;
using Newtonsoft.Json;
using ReallifeGamemode.Database.Entities;
using ReallifeGamemode.Database.Models;
using ReallifeGamemode.Server.Classes;
using ReallifeGamemode.Server.DrivingSchool;
using ReallifeGamemode.Server.Extensions;
using ReallifeGamemode.Server.Factions.Medic;
using ReallifeGamemode.Server.Finance;
using ReallifeGamemode.Server.Inventory;
using ReallifeGamemode.Server.Inventory.Interfaces;
using ReallifeGamemode.Server.Job;
using ReallifeGamemode.Server.Managers;
using ReallifeGamemode.Server.Services;
using ReallifeGamemode.Server.Types;
using ReallifeGamemode.Server.Util;
using ReallifeGamemode.Server.WeaponDeal;

/**
* @overview Life of German Reallife - Event Key (Key.cs)
* @author VegaZ, balbo
* @copyright (c) 2008 - 2018 Life of German
*/

namespace ReallifeGamemode.Server.Events
{
  public class Key : Script
  {
    #region User Key

    [RemoteEvent("keyPress:NUM2")]
    public void KeyPressNUM2(Player player)
    {
      if (!player.IsLoggedIn() || player.GetData<bool>("isDead")) return;
      if (player.GetData<bool>("editmode") == true && player.GetUser().IsAdmin(AdminLevel.HEADADMIN) == true)
      {
        var saveMode = player.GetData<string>("quicksavemode");
        switch (saveMode)
        {
          case "none":
            ChatService.SendMessage(player, "~r~Keinen Modus ausgewählt! ~y~/quicksavemode ~r~für mehr Infos!");
            break;

          case "blip":
            TempBlip tempBlip = NAPI.Data.GetWorldData("blipTemplate");
            SaveManager.OnSaveBlipData(player, tempBlip.Sprite.ToString(), tempBlip.Name, tempBlip.Scale.ToString(), tempBlip.Color.ToString(),
                tempBlip.Transparency.ToString(), 200.ToString(), tempBlip.ShortRange.ToString(), 0.ToString(), 0.ToString());
            player.SendNotification("~y~Blip~s~ erstellt!", false);
            break;

          case "atm":
            SaveManager.OnSaveBlipData(player, "500", "Geldautomat", 0.7.ToString(), "11",
                "0", "200", true.ToString(), 0.ToString(), 0.ToString());
            player.SendNotification("~y~ATM~s~ erstellt!", false);
            break;
        }
      }

      GroundItem.PickUpGroundItem(player);
    }

    /*
    [RemoteEvent("keyPress:LEFT_ARROW")]
    public void KeyPressLeftArrow(Player player)
    {
      if (!player.IsLoggedIn()) return;
      List<Player> nearbyPlayers = NAPI.Player.GetPlayersInRadiusOfPlayer(3, player);

      if (nearbyPlayers.Count > 1)
      {
        List<string> nearbyPlayerList = new List<string>();
        foreach (Player nearPlayer in nearbyPlayers)
        {
          if (nearPlayer.Name != player.Name)
          {
            nearbyPlayerList.Add(nearPlayer.Name);
          }
          else
          {
            continue;
          }
        }
        player.TriggerEvent("showPlayerInteraction", JsonConvert.SerializeObject(nearbyPlayerList));
      }
    }
    */

    [RemoteEvent("keyPress:RIGHT_ARROW")]
    public void KeyPressRightArrow(Player player)
    {
      if (!player.IsLoggedIn() || player.GetData<bool>("isDead")) return;
      User user = player.GetUser();

      if (!player.IsDuty())
      {
        return;
      }

      switch (user.FactionId)
      {
        //LSPD
        case 1:
        case 3:
          player.TriggerEvent("showFactionInteractionLSPD", user.FactionId, user.GetData<bool>("duty"), user.Faction.Name, user.FactionLeader);
          break;
        //Medic
        case 2:
          player.TriggerEvent("showFactionInteractionMedic", user.FactionId, user.GetData<bool>("duty"), user.Faction.Name, user.FactionLeader, Medic.ReviveTasks.Count.ToString(), Medic.HealTasks.Count.ToString(), Medic.FireTasks.Count.ToString());
          break;
      }
    }

    [RemoteEvent("keyPress:M")]
    public void KeyPressM(Player player)
    {
      if (!player.IsLoggedIn()) return;
      using var dbContext = new DatabaseContext();
      User u = player.GetUser(dbContext);
      if (u == null) return;

      var vehicles = dbContext.UserVehicles.Where(veh => veh.UserId == u.Id).OrderBy(veh => veh.Id).Select(v => new
      {
        v.Id,
        v.Model,
        Price = (v.Price ?? 0) * 0.6
      });

      var factionVehicles = dbContext.FactionVehicles.ToList().Where(f => f.GetOwners().Contains(u.FactionId ?? -1)).Select(f => new
      {
        f.Id,
        f.Model,
        Price = f.BuyPrice
      });

      Paycheck paycheck = null;
      if (Economy.Paychecks.ContainsKey(u.Id)) paycheck = Economy.Paychecks[u.Id];

      Licenses licenses = new Licenses(u.DriverLicenseVehicle, u.DriverLicenseBike, u.FlyingLicensePlane, u.WeaponLicense);

      var accountData = new
      {
        regDate = u.RegistrationDate.ToShortDateString(),
        adminLevel = u.AdminLevel.GetName(),
        points = u.Points,
        faction = u.Faction?.Name ?? "Zivilist",
        factionleader = u.Faction?.Name ?? "Zivilist",
        //factionleader = u.FactionLeader,
        stateFaction = u.Faction?.StateOwned,
        factionRank = u.GetFactionRank().RankName,
        group = u.Group?.Name ?? "Keine",
        groupRank = u.GroupRank.GetName(),
        paycheck,
        licenses,
        vehicles,
        factionVehicles,
        nextPayday = u.PaydayTimer,
        playTime = u.PlayedMinutes / 60,
        userWarn = u.warn,
      };

      var jobData = new
      {
        job = JobManager.GetJob(u.JobId ?? 0)?.Name ?? "Keiner",
        busskill = u.BusSkill,
        pilotskill = u.PilotSkill,
        wage = u.Wage,
        isActive = JobBase.GetPlayerInJob().Contains(player),
      };

      var memberList = dbContext.Users.Where(f => f.FactionId == u.FactionId && u.FactionId != 0).OrderByDescending(f => f.FactionRank.Order).ThenBy(f => f.Name).Select(m => new
      {
        username = m.Name,
        factionRank = m.FactionRank.Order,
        factionRankName = m.FactionRank.RankName,
        isLeader = m.FactionLeader,
        isOnline = m.Player.IsLoggedIn(),
      });

      string faction = u.Faction?.Name ?? "Zivilist";
      string factionleader = u.FactionLeader ? u.Faction.Name : null;
      string group = u.Group != null ? u.Group.Name : null;
      bool factionInvite = player.HasData("accept_faction_invite");
      bool groupInvite = player.HasData("accept_group_invite");
      bool ticket_boolean = player.HasData("ticket_boolean");
      int ticket_amount = 0;
      int pay_amount = 0;
      bool house = false;
      bool hasRentcar = player.GetData<bool>("hasRentcar") == true;

      if (u.House != null)
      {
        house = true;
      }

      if (player.HasData("ticket_amount"))
      {
        ticket_amount = player.GetData<int>("ticket_amount");
      }

      if (player.HasData("pay_amount"))
      {
        pay_amount = player.GetData<int>("pay_amount");
      }

      player.TriggerEvent("SERVER:InteractionMenu_OpenMenu", JsonConvert.SerializeObject(accountData), factionleader, JsonConvert.SerializeObject(memberList), JsonConvert.SerializeObject(jobData), faction, group, factionInvite, groupInvite, ticket_boolean, ticket_amount, pay_amount, JsonConvert.SerializeObject(hasRentcar), house);
    }

    [RemoteEvent("keyPress:E")]
    public void KeyPressE(Player player)
    {
      if (!player.IsLoggedIn() || player.GetData<bool>("isDead") || player.IsInVehicle) return;
      var user = player.GetUser();

      if (player.HasData("nearATM"))
      {
        ATMManager.ShowAtmUi(player, player.GetData<int>("nearATM"));
        return;
      }

      if (GroundItem.PickUpGroundItem(player))
      {
        return;
      }

      DutyPoint nearestDuty = PositionManager.DutyPoints.Find(d => d.Position.DistanceTo(player.Position) <= 1.5 && d.FactionId == user.FactionId);
      WeaponPoint nearestWeapon = PositionManager.WeaponPoints.Find(w => w.Position.DistanceTo(player.Position) <= 1.5 && w.FactionId == user.FactionId);
      JailReleasePoint nearestJailReleasePoint = PositionManager.JailReleasePoints.Find(j => j.Position.DistanceTo(player.Position) <= 1.5 && (user.FactionId == 1 || user.FactionId == 3) && user.GetData<bool>("duty"));
      ElevatorPoint nearestElevatorPoint = PositionManager.ElevatorPoints.Find(e => e.Position.DistanceTo(player.Position) <= 1.5 && (user.FactionId == 1 || user.FactionId == 2 || user.FactionId == 3));
      ClotheshopPoint nearestClotheShopPoint = PositionManager.clotheshopPoints.Find(s => s.Position.DistanceTo(player.Position) <= 1.5);
      FriseurPoint nearestFriseurPoint = PositionManager.friseurPoints.Find(s => s.Position.DistanceTo(player.Position) <= 1.5);
      ItemshopPoint nearestItemShopPoint = PositionManager.itemshopPoints.Find(s => s.Position.DistanceTo(player.Position) <= 1.5);
      JobPoint nearestJobPoint = PositionManager.JobPoints.Find(s => s.Position.DistanceTo(player.Position) <= 1.6);
      Player nearestCuffPlayer = PositionManager.cuffPoints.Find(s => s.Position.DistanceTo(player.Position) <= 1.6 && user.GetData<bool>("duty"));
      AmmunationPoint nearestAmmunationPoint = PositionManager.AmmunationPoints.Find(s => s.Position.DistanceTo(player.Position) <= 1.5);
      RentcarPoint nearestRentcarPoint = PositionManager.rentcarPoints.Find(s => s.Position.DistanceTo(player.Position) <= 1.5);

      if (user?.FactionId != null)
      {
        BehindVehiclePoint nearestBehindVehiclePoint = MarkerBehinVehicle.behindVehiclePoints.Find(s => s.marker.Position.DistanceTo(player.Position) <= 3 && WeaponDealManager.WEAPON_DEAL_FACTIONS.Contains(user.FactionId ?? 0));
        if (nearestBehindVehiclePoint != null)
        {
          if (player.HasAttachment("ammobox")) return;
          using var dbContext = new DatabaseContext();
          List<VehicleItem> vehicleItems = dbContext.VehicleItems.ToList().Where(f => f.GetVehicle().GetVehicle() == nearestBehindVehiclePoint.vehicle && InventoryManager.GetItemById(f.ItemId) is IWeaponDealItem).ToList();
          if (vehicleItems.Count == 0)
          {
            GTANetworkAPI.Vehicle vehicle = nearestBehindVehiclePoint.vehicle;

            if (vehicle.HasAttachment("weapondeal"))
            {
              vehicle.AddAttachment("weapondeal", true);
              vehicle.AddAttachment("weapondeal1", true);
              vehicle.AddAttachment("weapondeal2", true);
            }

            if (WeaponDealManager.checkWeaponDbyVehicle(vehicle))
            {
              vehicle.ResetData("WeaponDealLoad");
              vehicle.ResetData("weaponDeal");
              vehicle.ResetData("dealPoint");
            }

            nearestBehindVehiclePoint.vehicle.RemoveMarkerBehind();
            ServerVehicle sVeh = VehicleManager.GetServerVehicleFromVehicle(vehicle);
            sVeh.Spawn(vehicle);
            return;
          }
          foreach (var v in vehicleItems)
          {
            int itemToAdd = 0;
            for (int i = 1; i <= v.Amount; i++)
            {
              if (InventoryManager.GetUserInventoryWeight(player) + (i * InventoryManager.GetItemById(v.ItemId).Gewicht) > 40000)
              {
                break;
              }
              else
              {
                itemToAdd = i;
              }
            }
            if (itemToAdd == 0)
              break;

            v.Amount -= itemToAdd;
            if (v.Amount <= 0)
            {
              itemToAdd += v.Amount;
              dbContext.VehicleItems.Remove(v);
            }

            InventoryManager.AddItemToInventory(player, v.ItemId, itemToAdd);
            nearestBehindVehiclePoint.usePoint(player);
            dbContext.SaveChanges();
            return;
          }
        }
        if (nearestDuty != null)// Duty Point
        {
          var factionId = user.FactionId;

          if (user.GetData<bool>("duty") == false)
          {
            user.SetData("duty", true);
            player.SendNotification("Du bist nun ~g~im Dienst.");
            player.TriggerEvent("toggleDutyMode", true);
            player.TriggerEvent("abortSpawnschutz");
            if (user.FactionId == 2) //Fire Department
            {
              Medic.UpdateDutyMedics();
            }
            switch (factionId)
            {
              //FBI
              case 3:
                player.SetAccessories(2, 2, 0);
                break;
            }
            using (var context = new DatabaseContext())
            {
              List<CharacterCloth> clothes = context.CharacterClothes.Where(u => u.UserId == user.Id && u.Duty == true).ToList();

              foreach (var cloth in clothes)
              {
                if (cloth.SlotType == 0)
                {
                  player.SetClothes(cloth.SlotId, cloth.ClothId, 0);
                }
                else
                {
                  if (cloth.ClothId != -1)
                  {
                    player.SetAccessories(cloth.SlotId, cloth.ClothId, 0);
                  }
                  else
                  {
                    player.ClearAccessory(cloth.SlotId);
                  }
                }
              }
            }
          }
          else
          {
            user.SetData("duty", false);
            player.SendNotification("Du bist nun ~r~außer Dienst.");
            player.TriggerEvent("toggleDutyMode", false);
            Medic.UpdateDutyMedics();
            UpdateCharacterCloth.LoadCharacterDefaults(player);
          }
          user.SetBlipAndNametagColor();
        }

        //Rentcar Points
        if (nearestRentcarPoint != null)
        {
          if (player.IsInVehicle)
          {
            return;
          }

          //Noobspawn
          if (player.Position.DistanceTo(PositionManager.rentcarPoints[0].Position) <= 1.5)
          {
            player.TriggerEvent("showRentcarMenu", JsonConvert.SerializeObject(Rentcar.noobspawnVehicleProperties), "noobspawn");
          }
          //Stadthalle
          else if (player.Position.DistanceTo(PositionManager.rentcarPoints[1].Position) <= 1.5)
          {
            player.TriggerEvent("showRentcarMenu", JsonConvert.SerializeObject(Rentcar.stadthalleVehicleProperties), "lamesa");
          }
          //Knast
          else if (player.Position.DistanceTo(PositionManager.rentcarPoints[2].Position) <= 1.5)
          {
            player.TriggerEvent("showRentcarMenu", JsonConvert.SerializeObject(Rentcar.knastVehicleProperties), "stadthalle");
          }
          //Paleto
          else if (player.Position.DistanceTo(PositionManager.rentcarPoints[3].Position) <= 1.5)
          {
            player.TriggerEvent("showRentcarMenu", JsonConvert.SerializeObject(Rentcar.paletoVehicleProperties), "knast");
          }
          //Lamesa
          else if (player.Position.DistanceTo(PositionManager.rentcarPoints[4].Position) <= 1.5)
          {
            player.TriggerEvent("showRentcarMenu", JsonConvert.SerializeObject(Rentcar.paletoVehicleProperties), "paleto");
          }
        }

        if (nearestWeapon != null) // Weapon Point
        {
          List<string> primarys = new List<string>();
          List<string> secondarys = new List<string>();
          List<string> melees = new List<string>();
          List<string> specials = new List<string>();
          List<string> armor = new List<string>();
          List<string> timer = new List<string>();
          string dealTime = "Starten";
          primarys.Add("Keine");
          secondarys.Add("Keine");
          melees.Add("Keine");
          specials.Add("Keine");
          armor.Add("Keine");

          using (var context = new DatabaseContext())
          {
            if (player.HasAttachment("ammobox"))
            {
              player.AddAttachment("ammobox", true);
              player.ClearAnimation();
            }
            bool unloadedWeaponPackage = false;

            List<UserItem> fItem = context.UserItems.Where(u => u.UserId == user.Id).ToList();
            foreach (var item in fItem)
            {
              IItem iItem = InventoryManager.GetItemById(item.ItemId);
              if (iItem is IWeaponDealItem obj)
              {
                FactionWeapon weapon = context.FactionWeapons.Where(w => w.FactionId == user.FactionId && w.WeaponModel == iItem.Name).FirstOrDefault();
                if (weapon == null)
                {
                  context.Remove(item);
                  continue;
                }

                weapon.Ammount += item.Amount;
                ChatService.SendMessage(player, item.Amount + " " + iItem.Name + " wurden im Waffenlager hinzugefügt.");
                unloadedWeaponPackage = true;
                context.Remove(item);
              }
            }
            context.SaveChanges();

            if (unloadedWeaponPackage)
            {
              return;
            }

            List<FactionWeapon> weapons = context.FactionWeapons.Where(w => w.FactionId == user.FactionId).ToList();
            Database.Entities.Faction faction = context.Factions.Where(fac => fac.Id == user.FactionId).FirstOrDefault();

            if (faction.WeaponDealTime > 0)
              dealTime = "noch " + faction.WeaponDealTime.ToString() + " min. übrig";

            timer.Add(dealTime);

            foreach (var weapon in weapons)
            {
              if (weapon.Ammount <= 0)
                continue;
              switch (weapon.SlotID)
              {
                case 1:
                  if (user.FactionRank.Order >= weapon.Rank)
                    primarys.Add(weapon.WeaponModel.ToString());
                  break;

                case 2:
                  if (user.FactionRank.Order >= weapon.Rank)
                    secondarys.Add(weapon.WeaponModel.ToString());
                  break;

                case 3:
                  if (user.FactionRank.Order >= weapon.Rank)
                    melees.Add(weapon.WeaponModel.ToString());
                  break;

                case 4:
                  if (user.FactionRank.Order >= weapon.Rank)
                    specials.Add(weapon.WeaponModel.ToString());
                  break;

                case 5:
                  if (user.FactionRank.Order >= weapon.Rank)
                    armor.Add(weapon.WeaponModel.ToString());
                  break;
              }
            }

            List<string> allWeapons = context.FactionWeapons.Select(w => w.WeaponModel).Distinct().ToList();
            List<WeaponRackWeaponAmountInfo> amountInfos = new List<WeaponRackWeaponAmountInfo>();

            foreach (var weapon in allWeapons)
            {
              int amount = 0;

              var tempFactionWeapon = weapons.Where(f => f.WeaponModel == weapon).FirstOrDefault();
              if (tempFactionWeapon != null)
              {
                amount = tempFactionWeapon.Ammount;
              }

              amountInfos.Add(new WeaponRackWeaponAmountInfo()
              {
                WeaponModel = weapon,
                Amount = amount
              });
            }

            player.TriggerEvent("showWeaponMenu", primarys.ToArray(), secondarys.ToArray(), melees.ToArray(), specials.ToArray(), armor.ToArray(), JsonConvert.SerializeObject(timer.ToArray()), JsonConvert.SerializeObject(amountInfos));
          }
        }
        if (nearestJailReleasePoint != null)
        {
          List<string> criminals = new List<string>();
          criminals.Add("Keiner");
          foreach (Player target in NAPI.Pools.GetAllPlayers())
          {
            User c = target.GetUser();
            if (c == null)
            {
              continue;
            }

            if (c.JailTime > 0)
            {
              criminals.Add(c.Name);
            }
          }
          player.TriggerEvent("showJailMenu", JsonConvert.SerializeObject(criminals.ToArray()));
        }
        if (nearestCuffPlayer != null)
        {
          player.CuffPlayer(nearestCuffPlayer);
        }
      }
      if (nearestElevatorPoint != null)
      {
        List<string> stages = new List<string>();
        foreach (var e in PositionManager.ElevatorPoints)
        {
          if (e.Position.DistanceTo2D(player.Position) <= 30 && e.Position.DistanceTo(player.Position) > 1.5)
          {
            stages.Add(e.Stage);
          }
        }
        player.TriggerEvent("showElevatorMenu", JsonConvert.SerializeObject(stages.ToArray()));
      }
      if (nearestClotheShopPoint != null)
      {
        if (user.GetData<bool>("duty"))
        {
          player.SendNotification("~r~Im Dienst kannst du keine Kleidung kaufen", false);
          return;
        }
        if (JobBase.GetPlayerInJob().Contains(player))
        {
          player.SendNotification("~r~Im aktiven Job kannst du keine Kleidung kaufen", false);
          return;
        }
        nearestClotheShopPoint.clotheShop.LoadShopNUI(player);
      }
      if (nearestItemShopPoint != null)
      {
        nearestItemShopPoint.itemShop.LoadShopNUI(player);
      }
      if (nearestFriseurPoint != null)
      {
        if (user.GetData<bool>("duty"))
        {
          player.SendNotification("~r~Im Dienst wirst du nicht vom Friseur bedient", false);
          return;
        }
        if (JobBase.GetPlayerInJob().Contains(player))
        {
          player.SendNotification("~r~Im aktiven Job wirst du nicht vom Friseur bedient", false);
          return;
        }
        nearestFriseurPoint.friseurShop.LoadShopNUI(player);
      }
      if (nearestAmmunationPoint != null)
      {
        if (!user.WeaponLicense)
        {
          player.SendNotification("~r~Du besitzt keinen Waffenschein");
        }
        else
        {
          nearestAmmunationPoint.Ammunation.LoadShopNUI(player);
        }
      }
      if (CharacterCreator.surgeryPoint.DistanceTo(player.Position) <= 1.5)
      {
        if (user.GetData<bool>("duty"))
        {
          player.SendNotification("~r~Im Dienst kannst du nicht operiert werden", false);
          return;
        }
        if (JobBase.GetPlayerInJob().Contains(player))
        {
          player.SendNotification("~r~Im aktiven Job kannst du nicht operiert werden", false);
          return;
        }
        if (user.Wanteds > 0)
        {
          player.SendNotification("~r~Wenn du gesucht wirst kannst du nicht operiert werden", false);
          return;
        }

        var freeSurgery = user.FreeSurgery;
        if (freeSurgery == false && user.BankAccount.Balance < CharacterCreator.SURGERY_PRICE)
        {
          ChatService.ErrorMessage(player, $"Du benötigst {CharacterCreator.SURGERY_PRICE.ToMoneyString()} auf dem Bankkonto um die Operation durchzuführen");
          return;
        }

        ChatService.SendMessage(player, "~r~ACHTUNG! Dadurch wird dein alter Charakter gelöscht. Du kannst dir hiermit einen neuen erstellen.");
        ChatService.SendMessage(player, "Beim Wechsel des Geschlechts verlierst du ebenfalls deine gekaufte Kleidung");
        if (freeSurgery == true)
        {
          ChatService.SendMessage(player, "Du kannst deinen Charakter dieses mal kostenlos erstellen");
        }
        else
        {
          ChatService.SendMessage(player, "Die Änderung des Charakters kostet ~g~" + CharacterCreator.SURGERY_PRICE.ToMoneyString());
        }
        ChatService.SendMessage(player, "Du kannst die Charaktererstellung wieder verlassen und behältst deinen alten Charakter!");
        ChatService.SendMessage(player, "Bitte starte mit ~g~J");

        player.SetData<bool>("charSurgery", true);
        NAPI.Task.Run(() =>
        {
          if (player.GetData<bool>("charSurgery") == true)
          {
            player.ResetData("charSurgery");
            player.SendNotification("~r~Chirurg-Angebot abgebrochen.");
          }
        }, 30000);
      }
      if (user.FactionLeader)
      {
        player.TriggerEvent("CLIENT:StartGangwar");
      }

      if (nearestJobPoint != null)
      {
        if (player.Vehicle != null) return;
        Job.JobBase job = JobManager.GetJob(player.GetUser().JobId ?? -1);
        JobManager jobManager = new JobManager();
        if (nearestJobPoint.jobId == player.GetUser().JobId)
        {
          if (job.GetUsersInJob().Contains(player))
          {
            jobManager.StopJob(player);
            return;
          }
          if (!job.GetUsersInJob().Contains(player))
          {
            if (user.GetData<bool>("duty"))
            {
              player.SendNotification("~r~Im Dienst kannst du keinen Job ausführen", false);
              return;
            }
            if (user.Wanteds > 0)
            {
              player.SendNotification("~r~Mit Wanteds kannst du keinen Job starten", false);
              return;
            }
            if (player.GetUser().JobId == 3)
            {
              if (nearestJobPoint.Skill > user.PilotSkill)
              {
                player.SendChatMessage("~y~[JOB] ~r~Dein Skilllevel ist noch zu niedrig.");
                return;
              }
              jobManager.StartJobEvent(player);
              job.StartJob(player);
              JobManager.GetJob<PilotJob>().StartPilotRoute(player, nearestJobPoint.Skill);
            }
            else
            {
              jobManager.StartJobEvent(player);
            }
            return;
          }
        }
        else
        {
          player.SendNotification("~r~[Fehler] ~w~ Du hast diesen Job nicht angenommen.");
          return;
        }
      }
    }

    [RemoteEvent("keyPress:I")]
    public void KeyPressI(Player player)
    {
      if (!player.IsLoggedIn() || player.GetData<bool>("isDead")) return;
      if (player.GetData<bool>("isDead")) return;

      player.TriggerEvent("inventoryShow");
      InventoryManager.SetBackpackItems(player);
    }

    [RemoteEvent("keyPress:J")]
    public void KeyPressJ(Player player)
    {
      if (!player.IsLoggedIn() || player.GetData<bool>("isDead")) return;
      if (player.GetData<bool>("healDecision") == true)
      {
        player.ResetData("healDecision");
        Medic.MakeHealDecision(player, true);
        return;
      }

      if (player.GetData<bool>("SellVehicleDecision") == true && player.HasData("VehicleToSell"))
      {
        InteractionManager.SellServerVehicle(player, player.GetData<int>("VehicleToSell"));
        player.ResetData("SellVehicleDecision");
        player.ResetData("VehicleToSell");
        return;
      }

      if (player.GetData<bool>("charSurgery") == true)
      {
        CharacterCreator.StartSurgery(player);
        player.ResetData("charSurgery");
      }

      User u = player.GetUser();

      if (u.JobId == null) return;

      JobBase job = JobManager.GetJob(u.JobId.Value);

      dynamic data = null;

      if (job.Id == 1 && job.GetUsersInJob().Contains(player))
      {
        var taxiCalls = JobManager.GetJob<TaxiDriverJob>().TaxiContracts;
        if (!taxiCalls.Any(t => t.Driver?.Handle == player.Handle)) // Spieler in keiner aktiven Fahrt
        {
          data = new
          {
            job.Id,
            Status = 0,
            JobData = new
            {
              TaxiCalls = taxiCalls
                  .Where(t => t.Driver == null)
                  .Select(t => new
                  {
                    t.Name,
                    Distance = Math.Round(t.Position.DistanceTo(player.Position), 0)
                  })
                  .OrderBy(t => t.Distance)
            }
          };
        }
        else // Spieler in aktiver Fahrt
        {
          data = new
          {
            job.Id,
            Status = 1,
            JobData = new
            {
              taxiCalls.Where(t => t.Driver.Handle == player.Handle).First().Name
            }
          };
        }
      }
      //JobPoint nearJobPoint = PositionManager.JobPoints.Find(p => p.Position.DistanceTo(player.Position) <= 2);
      if (u.JobId == 2 || u.JobId == 3 || u.JobId == 4)
      {
        return;
      }

      var json = JsonConvert.SerializeObject(data);

      player.TriggerEvent("SERVER:Job_ShowJobMenu", job.Name, json);
    }

    [RemoteEvent("keyPress:O")]
    public void KeyPressO(Player player)
    {
      if (!player.IsLoggedIn()) return;

      List<Player> players = NAPI.Pools.GetAllPlayers().Where(p => p.IsLoggedIn() == true).OrderBy(o => o.Handle.Value).ToList();

      var listPlayers = players.Select(p =>
      {
        User u = p.GetUser();

        return new
        {
          Id = p.Handle.Value,
          Name = p.Name + (u.PlayedMinutes <= GlobalHelper.newbiePlayedMinutesThreshold ? "<span class=\"player__status\">Neuling</span>" : ""),
          FactionId = u?.FactionId ?? 0,
          p.Ping
        };
      });

      player.TriggerEvent("showPlayerlist", JsonConvert.SerializeObject(listPlayers));
    }

    [RemoteEvent("keyPress:K")]
    public void KeyPressK(Player player)
    {
      if (!player.IsLoggedIn() || player.GetData<bool>("isDead")) return;
      var user = player.GetUser();
      if (user == null)
      {
        return;
      }

      if (user?.FactionId != null)
      {
        DutyPoint nearest = PositionManager.DutyPoints.Find(d => d.Position.DistanceTo(player.Position) <= 1.5);
        if (nearest == null) return;
        if (player.Position.DistanceTo(nearest.Position) <= 1.5 && nearest.FactionId == user.FactionId)
        {
          List<string> hats = new List<string>();
          List<string> tops = new List<string>();
          List<string> legs = new List<string>();
          List<string> shoes = new List<string>();

          using (var context = new DatabaseContext())
          {
            var gender = user.GetCharacter().Gender;
            List<DutyCloth> clothes = context.DutyClothes.Where(c => c.FactionId == user.FactionId && c.Gender == gender).ToList();
            foreach (var cloth in clothes)
            {
              if (cloth.SlotType == 1)
              {
                if (cloth.ClothId != -1)
                {
                  hats.Add(cloth.ClothId.ToString());
                }
                else
                {
                  hats.Add("Keinen");
                }
                continue;
              }
              switch (cloth.SlotId)
              {
                case 11:
                  tops.Add(cloth.ClothId.ToString());
                  break;

                case 4:
                  legs.Add(cloth.ClothId.ToString());
                  break;

                case 6:
                  shoes.Add(cloth.ClothId.ToString());
                  break;
              }
            }
          }
          player.TriggerEvent("showDutyClothMenu", hats.ToArray(), tops.ToArray(), legs.ToArray(), shoes.ToArray());
        }
      }
    }

    [RemoteEvent("keyPress:L")]
    public void KeyPressL(Player player)
    {
      if (!player.IsLoggedIn() || player.GetData<bool>("isDead")) return;
      DoorManager.ChangeDoorState(player);
    }

    [RemoteEvent("keyPress:N")]
    public void KeyPressN(Player player)
    {
      if (!player.IsLoggedIn() || player.GetData<bool>("isDead")) return;

      if (player.GetData<bool>("healDecision") == true)
      {
        player.ResetData("healDecision");
        Medic.MakeHealDecision(player, false);
        return;
      }
      if (player.GetData<bool>("SellVehicleDecision") == true && player.HasData("VehicleToSell"))
      {
        player.ResetData("SellVehicleDecision");
        player.ResetData("VehicleToSell");
        player.SendNotification("~r~Du hast den Fahrzeugverkauf abgebrochen");
        return;
      }

      if (!player.IsInVehicle) return;
      if (player.VehicleSeat != 0) return;

      GTANetworkAPI.Vehicle v = player.Vehicle;

      User u = player.GetUser();
      if (u == null) return;

      if (NAPI.Entity.GetEntityVelocity(v).Length() > 1 && v.Class != 16)
      {
        player.SendNotification("~r~Der Motor kann nur im Stand betätigt werden.", true);
        return;
      }

      bool state = VehicleStreaming.GetEngineState(v);
      ServerVehicle sV = v.GetServerVehicle();
      if (sV != null)
      {
        if (sV is ShopVehicle)
        {
          VehicleStreaming.SetEngineState(v, false);
          return;
        }
        else if (sV is FactionVehicle fV)
        {
          if ((fV.Model == WeaponDealManager.WEAPON_DEAL_GANG_VEHICLE_HASH || fV.Model == WeaponDealManager.WEAPON_DEAL_STAATSFRAK_VEHICLE_HASH)
            && WeaponDealManager.WEAPON_DEAL_FACTIONS.Contains(u.FactionId ?? 0))
          {
            VehicleStreaming.SetEngineState(v, !state);
          }
          else if (!fV.GetOwners().Contains(u.FactionId ?? 0) && !state && !(u.IsAdmin(AdminLevel.HEADADMIN) && player.IsAdminDuty()))
          {
            player.SendNotification("~r~Du hast keinen Schlüssel.");
            return;
          }
        }
        else if (sV is GroupVehicle gV)
        {
          if (gV.GroupId != u.Group.Id && !state && !u.IsAdmin(AdminLevel.ADMIN3) && player.IsAdminDuty())
          {
            player.SendNotification("~r~Du hast keinen Schlüssel.");
            return;
          }
        }
        else if (sV is JobVehicle jV)
        {
          if (jV.JobId != player.GetUser().JobId && !state && !(u.IsAdmin(AdminLevel.HEADADMIN) && player.IsAdminDuty()))
          {
            player.SendNotification("~r~Du hast keinen Schlüssel.");
            return;
          }
          else
          {
            if (!jV.GetJob().GetUsersInJob().Contains(player) && !player.IsAdminDuty())
            {
              player.SendNotification("~y~[JOB] ~w~Du musst den Job vorher starten!");
              return;
            }
          }
        }
        else if (sV is UserVehicle uV)
        {
          if (u.IsAdmin(AdminLevel.HEADADMIN) && player.IsAdminDuty())
          {
          }
          else if (uV.UserId != u.Id && !u.IsAdmin(AdminLevel.HEADADMIN))
          {
            player.SendNotification("~r~Du hast keinen Schlüssel.");
            return;
          }
        }
      }
      VehicleStreaming.SetEngineState(v, !state);
    }

    [RemoteEvent("keyPress:Z")]
    public void KeyPressX(Player player)
    {
      if (!player.IsLoggedIn() || player.GetData<bool>("isDead")) return;

      if (!player.IsInVehicle)
      {
        Vehicle.VehicleMenuLockCarEvent(player);
      }

      if (player.IsInVehicle && player.VehicleSeat == 0)
      {
        ServerVehicle veh = player.Vehicle.GetServerVehicle();
        if (veh != null)
        {
          User u = player.GetUser();
          if (veh is FactionVehicle fV && !fV.GetOwners().Contains(u.FactionId ?? 0) && (!u.IsAdmin(AdminLevel.ADMIN3)))
          {
            return;
          }
          else if (veh is ShopVehicle)
          {
            return;
          }
        }
        player.TriggerEvent("ToggleVehicleMenu");
      }
    }

    [RemoteEvent("keyPress:ControllH")]
    public void KeyPressControllH(Player player)
    {
      player.CheckToggleSurrender();
    }

    #endregion User Key
  }
}
