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

namespace ReallifeGamemode.Server.Managers
{
  internal class TuningManager : Script
  {
    private static List<ColShape> tuningGarages = new List<ColShape>();

    public static void LoadTuningGarages()
    {
      using (var dbContext = new DatabaseContext())
      {
        foreach (TuningGarage garage in dbContext.TuningGarages)
        {
          AddTuningGarage(garage.Position);
        }
      }
    }

    /// <summary>
    /// Fügt eine Tuning-Garage zum Spiel hinzu
    /// </summary>
    /// <param name="pos">Die Position der Garage</param>
    public static void AddTuningGarage(Vector3 pos)
    {
      NAPI.Blip.CreateBlip(446, pos, 0.7f, 4, "Los Santos Customs", shortRange: true);

      ColShape colShape = NAPI.ColShape.CreateSphereColShape(pos, 5, 0);

      colShape.OnEntityEnterColShape += (cs, c) =>
      {
        using var dbContext = new DatabaseContext();
        if (c.IsInVehicle && c.VehicleSeat == 0)
        {
          Vehicle v = c.Vehicle;
          if (v.GetServerVehicle() is FactionVehicle fV && fV.GetOwners().Any(fV => dbContext.Factions.Where(f => f.Id == fV && f.StateOwned).Any()))
          {
            return;
          }
          c.TriggerEvent("showTuningInfo");
        }
      };

      colShape.OnEntityExitColShape += (cs, c) =>
      {
        c.TriggerEvent("hideTuningInfo", true);
      };

      tuningGarages.Add(colShape);
    }

    public static void ApplyTuningToServerVehicle(ServerVehicle sVeh)
    {
      Vehicle veh = VehicleManager.GetVehicleFromServerVehicle(sVeh);
      if (veh == null) return;

      veh.SetSharedData("mod18", false);

      using (var dbContext = new DatabaseContext())
      {
        foreach (VehicleMod vMod in dbContext.VehicleMods.ToList().FindAll(vM => vM.ServerVehicleId == sVeh.Id))
        {
          if (vMod.Slot == 18)
          {
            veh.SetSharedData("mod" + vMod.Slot, true);
          }
          else if (vMod.Slot == 22)
          {
            int color = vMod.ModId - 2;
            if (vMod.ModId == 0) color = -1;
            if (vMod.ModId == 1) color = 13;
            veh.SetSharedData("headlightColor", color);
          }
          else veh.SetMod(vMod.Slot, vMod.ModId - 1);
        }
      }
    }

    [RemoteEvent("startPlayerTuning")]
    public void StartPlayerTuning(Player player)
    {
      if (!player.IsInVehicle) return;

      player.TriggerEvent("showTuningMenu");
    }

    [RemoteEvent("repairVehicle")]
    public void RepairVehicle(Player player)
    {
      if (!player.IsInVehicle) return;
      player.Vehicle.Repair();
    }

    [RemoteEvent("setVehicleMod")]
    public void SetVehicleMod(Player player, int slot, int index)
    {
      Vehicle pV = player.Vehicle;
      if (index == 0) index--;

      if (slot != 18)
      {
        if (slot == 22)
        {
          int color = index - 2;
          if (index == 0) color = -1;
          if (index == 1) color = 13;
          pV.SetSharedData("headlightColor", color);
        }
        else
        {
          pV.SetMod(slot, index - 1);
        }
      }
      else
      {
        bool newVal = index == -1 ? false : true;
        pV.SetSharedData("mod" + slot, newVal);
        NAPI.ClientEvent.TriggerClientEventForAll("vehicleToggleMod", pV, slot, newVal);
      }

      ServerVehicle sV = player.Vehicle.GetServerVehicle();
      if (sV == null) return;

      using (var dbContext = new DatabaseContext())
      {
        VehicleMod vMod = dbContext.VehicleMods.FirstOrDefault(m => m.ServerVehicleId == sV.Id && m.Slot == slot);
        if (vMod == null && index != -1)
        {
          vMod = new VehicleMod
          {
            ServerVehicleId = sV.Id,
            Slot = slot,
            ModId = index
          };
          dbContext.VehicleMods.Add(vMod);
        }
        else if (vMod != null && index == -1)
        {
          dbContext.VehicleMods.Remove(vMod);
        }
        else
        {
          if (vMod == null)
          {
            vMod = new VehicleMod
            {
              ServerVehicleId = sV.Id,
              Slot = slot
            };
            dbContext.VehicleMods.Add(vMod);
          }
          vMod.ModId = index;
        }
        dbContext.SaveChanges();
      }
    }

    [RemoteEvent("CLIENT:TuningManager_SetVehicleColor")]
    public void TuningManagerSetVehicleColor(Player player, bool primarySecondary, int color)
    {
      Vehicle veh = player.Vehicle;
      if (primarySecondary)
      {
        veh.PrimaryColor = color;
      }
      else
      {
        veh.SecondaryColor = color;
      }

      using var dbContext = new DatabaseContext(true);
      ServerVehicle serverVeh = VehicleManager.GetServerVehicleFromVehicle(veh, dbContext);

      if (serverVeh == null)
      {
        return;
      }

      if (primarySecondary)
      {
        serverVeh.PrimaryColor = color;
      }
      else
      {
        serverVeh.SecondaryColor = color;
      }

      dbContext.SaveChanges();
    }
  }
}
