using System;
using System.Collections.Generic;
using System.Linq;
using GTANetworkAPI;
using ReallifeGamemode.Database.Entities;
using ReallifeGamemode.Database.Models;
using ReallifeGamemode.Server.Extensions;
using ReallifeGamemode.Server.Managers;
using ReallifeGamemode.Server.Services;

namespace ReallifeGamemode.Server.WeaponDeal
{
  public class WeaponDealManager : Script
  {
    public static readonly int[] WEAPON_DEAL_GANG_IDS = new int[] { 5, 7, 8 };
    public static readonly int[] WEAPON_DEAL_STAATSFRAK_IDS = new int[] { 1, 3 };

    public static int[] WEAPON_DEAL_FACTIONS => WEAPON_DEAL_GANG_IDS.Concat(WEAPON_DEAL_STAATSFRAK_IDS).Distinct().ToArray();

    public static readonly VehicleHash WEAPON_DEAL_GANG_VEHICLE_HASH = VehicleHash.Gburrito2;
    public static readonly VehicleHash WEAPON_DEAL_STAATSFRAK_VEHICLE_HASH = VehicleHash.Policet;

    private const int WEAPON_AMOUNT_GANG = 2;
    private const int WEAPON_AMOUNT_COP = 4;
    private const int WEAPON_AMOUNT_COP_STUNGUN = 4;
    public static bool checkWeaponDbyVehicle(Vehicle vehicle)
    {
      if ((vehicle.HasData("WeaponDealLoad") && vehicle.GetData<bool>("WeaponDealLoad") == true) ||
        (vehicle.HasData("weaponDeal") && vehicle.GetData<bool>("weaponDeal") == true))
      {
        return true;
      }

      return false;
    }

    [RemoteEvent("startWeaponDeal")]
    public void SrvEVENT_startWeaponDeal(Player client)
    {
      var user = client.GetUser();
      if (user == null || user.FactionId == null)
      {
        return;
      }

      using (var context = new DatabaseContext(true))
      {
        FactionVehicle factionVehicle = context.FactionVehicles.Where(f => f.Model == WEAPON_DEAL_GANG_VEHICLE_HASH || f.Model == WEAPON_DEAL_STAATSFRAK_VEHICLE_HASH)
          .ToList()
          .Where(f => f.GetOwners().Contains(user.FactionId ?? 0))
          .FirstOrDefault();

        if (factionVehicle == null)
        {
          ChatService.ErrorMessage(client, "Deine Fraktion hat kein geeignetes Fahrzeug für einen Waffentransport");
          return;
        }

        Vehicle fVeh = VehicleManager.GetVehicleFromServerVehicle(factionVehicle);

        if (checkWeaponDbyVehicle(fVeh))
        {
          ChatService.ErrorMessage(client, "Es läuft aktuell schon ein Waffentransport");
          return;
        }

        float distance = fVeh.Position.DistanceTo2D(client.Position);
        if ((distance > 80 && factionVehicle.Model == WEAPON_DEAL_GANG_VEHICLE_HASH) || (distance > 400 && factionVehicle.Model == WEAPON_DEAL_STAATSFRAK_VEHICLE_HASH))
        {
          ChatService.ErrorMessage(client, "Der Transporter ist zu weit entfernt");
          return;
        }

        WeaponDealPoints.factionWeaponDeal[user.FactionId.Value] = -1;
        Vector3 vector;
        vector = WeaponDealPoints.getRndWD_Route(user.FactionId.Value);
        if (vector == new Vector3())
          return;
        fVeh.SetData<Vector3>("weaponDealPoint", vector);

        if (user.Faction.WeaponDealTime > 0)
        {
          ChatService.ErrorMessage(client, "Du kannst noch keinen Waffendeal starten");
          return;
        }

        int i = 0;
        string msg = "";
        foreach (var point in WeaponDealPoints.WT_Route)
        {
          i++;
          if (point != vector)
            continue;

          switch (i)
          {
            case 1:
              msg = "Das Madrazo Kartell scheint am Strand noch einige Waffen verbuddelt zu haben";
              break;

            case 2:
              msg = "Die Lost MC scheint wieder im Waffen-Business aktiv zu sein";
              break;

            case 3:
              msg = "Ein paar hochrangige Mitglieder der U.S. Armee versuchen alte sowjetische Waffen loszuwerden";
              break;

            case 4:
              msg = "Die Triaden können uns mit östlichen Importen beliefern";
              break;

            case 5:
              msg = "Die albanische Mafia will wohl wieder Geschäfte mit uns machen";
              break;

            case 6:
              msg = "Die Waffen der Russen waren schon immer zuverlässig";
              break;
          }
        }

        if (user.Faction.Id == 1 || user.Faction.Id == 3)
        {
          msg = "Die Waffenlieferung steht zur Abholung bereit";
        }

        ChatService.BroadcastFaction($"~y~[WAFFENDEAL]~s~ {msg}.", user.Faction);

        string vehName = NAPI.Vehicle.GetVehicleDisplayName(factionVehicle.Model);
        ChatService.SendMessage(client, $"~y~[WAFFENDEAL]~s~ Steige in den {vehName} ein und fahre zum Übergabepunkt.");
        fVeh.SetData("weaponDeal", true);
        InventoryManager.RemoveAllItemsfromVehicleInventory(fVeh);
        Faction fac = context.Factions.Where(f => f.Id == user.FactionId).FirstOrDefault();

        if (fac.Id == 1 | fac.Id == 3)
        {
          fac.WeaponDealTime = 180;
          context.SaveChanges();
        }
        else
        {
          fac.WeaponDealTime = 60;
          context.SaveChanges();
        }
      }
    }

    /*
    public static void WeaponDealTimer()
    {
      System.Timers.Timer timer = new System.Timers.Timer(60000);
      timer.Start();
      timer.Elapsed += Timer_Elapsed;
    }
    */

    public static void Timer_Elapsed()
    {
      using (var context = new DatabaseContext())
      {
        List<Faction> fac = context.Factions.ToList<Faction>();
        foreach (var faction in fac)
        {
          if (faction.WeaponDealTime > 0)
            faction.WeaponDealTime -= 1;
        }
        context.SaveChanges();
      }
    }

    [ServerEvent(Event.PlayerWeaponSwitch)]
    public void OnPlayerWeaponSwitch(Player player, WeaponHash oldWeapon, WeaponHash newWeapon)
    {
      if (!player.HasAttachment("ammobox")) return;
      NAPI.Player.SetPlayerCurrentWeapon(player, WeaponHash.Unarmed);
    }

    [RemoteEvent("loadWeaponTransport")]
    public void SrvEVENT_loadWeaponTransport(Player client)
    {
      var veh = client.Vehicle;

      if (veh == null)
      {
        return;
      }
      if ((VehicleHash)veh.Model != WEAPON_DEAL_GANG_VEHICLE_HASH && (VehicleHash)veh.Model != WEAPON_DEAL_STAATSFRAK_VEHICLE_HASH)
      {
        return;
      }

      User user = client.GetUser();
      using (var context = new DatabaseContext())
      {
        FactionVehicle factionVehicle = context.FactionVehicles
          .Where(f => f.Model == WEAPON_DEAL_GANG_VEHICLE_HASH || f.Model == WEAPON_DEAL_STAATSFRAK_VEHICLE_HASH)
          .ToList()
          .Where(f => f.GetOwners().Contains(user.FactionId ?? 0))
          .FirstOrDefault();

        var owners = factionVehicle.GetOwners();

        Vehicle fVeh = VehicleManager.GetVehicleFromServerVehicle(factionVehicle);
        fVeh.SetData("weaponDeal", false);
        fVeh.SetData("WeaponDealLoad", true);
        fVeh.AddAttachment("weapondeal", false);
        fVeh.AddAttachment("weapondeal1", false);
        fVeh.AddAttachment("weapondeal2", false);
        InventoryManager.RemoveAllItemsfromVehicleInventory(fVeh);
        int oMembers = NAPI.Pools.GetAllPlayers().Where(p => !p.IsAfk() && p.IsLoggedIn() && p.GetUser(context).FactionId == user.FactionId).Count();

        if (owners.Any(o => WEAPON_DEAL_GANG_IDS.Contains(o))) // Gang WT
        {
          VehicleItem item = new VehicleItem() { ItemId = 2, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_GANG * oMembers }; //pistol50
          InventoryManager.AddItemToVehicleInventory(fVeh, item.ItemId, item.Amount);
          VehicleItem item3 = new VehicleItem() { ItemId = 9, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_GANG * oMembers }; //PumpShotgun
          InventoryManager.AddItemToVehicleInventory(fVeh, item3.ItemId, item3.Amount);
          VehicleItem item2 = new VehicleItem() { ItemId = 10, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_GANG * oMembers }; //Schutzweste
          InventoryManager.AddItemToVehicleInventory(fVeh, item2.ItemId, item2.Amount);
          VehicleItem item4 = new VehicleItem() { ItemId = 7, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_GANG * oMembers }; //CompactRifle
          InventoryManager.AddItemToVehicleInventory(fVeh, item4.ItemId, item4.Amount);
          VehicleItem item5 = new VehicleItem() { ItemId = 13, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_GANG * oMembers }; //AssaultRifle
          InventoryManager.AddItemToVehicleInventory(fVeh, item5.ItemId, item5.Amount);
        }
        else if (owners.Contains(1)) // LSPD
        {
          VehicleItem item = new VehicleItem() { ItemId = 1, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //pistol
          InventoryManager.AddItemToVehicleInventory(fVeh, item.ItemId, item.Amount);
          VehicleItem item2 = new VehicleItem() { ItemId = 2, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //Pistol50
          InventoryManager.AddItemToVehicleInventory(fVeh, item2.ItemId, item2.Amount);
          VehicleItem item3 = new VehicleItem() { ItemId = 5, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //SMG
          InventoryManager.AddItemToVehicleInventory(fVeh, item3.ItemId, item3.Amount);
          VehicleItem item4 = new VehicleItem() { ItemId = 9, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //PumpShotgun
          InventoryManager.AddItemToVehicleInventory(fVeh, item4.ItemId, item4.Amount);
          VehicleItem item5 = new VehicleItem() { ItemId = 10, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //Schutzweste
          InventoryManager.AddItemToVehicleInventory(fVeh, item5.ItemId, item5.Amount);
          VehicleItem item6 = new VehicleItem() { ItemId = 11, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP_STUNGUN * oMembers }; //Stungun
          InventoryManager.AddItemToVehicleInventory(fVeh, item6.ItemId, item6.Amount);
          VehicleItem item7 = new VehicleItem() { ItemId = 14, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP_STUNGUN * oMembers }; // AssaultSmg
          InventoryManager.AddItemToVehicleInventory(fVeh, item7.ItemId, item7.Amount);
        }
        else if (owners.Contains(3)) // FIB
        {
          VehicleItem item = new VehicleItem() { ItemId = 3, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //pistol_mk2
          InventoryManager.AddItemToVehicleInventory(fVeh, item.ItemId, item.Amount);
          VehicleItem item2 = new VehicleItem() { ItemId = 4, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //Combatpistol
          InventoryManager.AddItemToVehicleInventory(fVeh, item2.ItemId, item2.Amount);
          VehicleItem item3 = new VehicleItem() { ItemId = 6, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //Carbinrifle
          InventoryManager.AddItemToVehicleInventory(fVeh, item3.ItemId, item3.Amount);
          VehicleItem item4 = new VehicleItem() { ItemId = 8, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //Sniperrifle
          InventoryManager.AddItemToVehicleInventory(fVeh, item4.ItemId, item4.Amount);
          VehicleItem item5 = new VehicleItem() { ItemId = 10, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //Schutzweste
          InventoryManager.AddItemToVehicleInventory(fVeh, item5.ItemId, item5.Amount);
          VehicleItem item6 = new VehicleItem() { ItemId = 11, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP_STUNGUN * oMembers }; //Stungun
          InventoryManager.AddItemToVehicleInventory(fVeh, item6.ItemId, item6.Amount);
          VehicleItem item7 = new VehicleItem() { ItemId = 12, VehicleId = factionVehicle.Id, Amount = WEAPON_AMOUNT_COP * oMembers }; //CombatPDW
          InventoryManager.AddItemToVehicleInventory(fVeh, item7.ItemId, item7.Amount);
        }

        ChatService.BroadcastFaction("~y~[WAFFENDEAL] ~w~Der Transporter wurde erfolgreich beladen.", new List<int>() { client.GetUser().Faction.Id });
        client.SendChatMessage("~y~[WAFFENDEAL] ~w~Fahre nun zu deiner Base zurück.");
        BasePoints basePoints = new BasePoints();
        basePoints.getbase(user.FactionId, client);
      }
    }
  }

  public class WeaponRackWeaponAmountInfo
  {
    public string WeaponModel { get; set; }
    public int Amount { get; set; }
  }
}
