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

namespace ReallifeGamemode.Server.Events
{
  public class UpdateCharacterCloth : Script
  {
    [RemoteEvent("updateDutyProp")]
    public void UpdateDutyProp(Player player, int componentId, int componentVariation)
    {
      if (componentId != -1)
      {
        player.SetAccessories(componentId, componentVariation, 0);
      }
      else
      {
        player.ClearAccessory(0);
        player.ClearAccessory(1);
        player.ClearAccessory(2);
      }
    }

    [RemoteEvent("updateDutyCloth")]
    public void UpdateDutyCloth(Player player, int componentId, int componentVariation)
    {
      if (componentId == 11)
      {
        //TODO Spezielle Duty Kleidung in Datenbank einpflegen (Ergibt bei Cop-Kleidung NULL)
        using (var context = new DatabaseContext())
        {
          var character = player.GetUser().GetCharacter();

          var combination = context.ClothCombinations.FirstOrDefault(c => c.Top == componentVariation && c.Gender == character.Gender);
          player.SetClothes(11, componentVariation, 0);
          if (combination != null)
          {
            player.SetClothes(3, combination.Torso, 0);
            player.SetClothes(8, combination.Undershirt, 0);
          }
        }
      }
      else
      {
        player.SetClothes(componentId, componentVariation, 0);
      }
    }

    [RemoteEvent("saveCharacterCloth")]
    public void SaveDutyCloth(Player client, string JSlotType, string JSlotId, string JClothId)
    {
      using (var context = new DatabaseContext())
      {
        int[] slotType = JsonConvert.DeserializeObject<int[]>(JSlotType);
        int[] slotId = JsonConvert.DeserializeObject<int[]>(JSlotId);
        int[] clothId = JsonConvert.DeserializeObject<int[]>(JClothId);

        User user = client.GetUser();
        user = context.Users.FirstOrDefault(u => u.Id == user.Id);

        var character = client.GetUser().GetCharacter();

        var charClothes = context.CharacterClothes.FirstOrDefault(c => c.UserId == user.Id);
        if (charClothes == null)
        {
          for (var x = 0; x < slotType.Length; x++)
          {
            CharacterCloth newCloth = new CharacterCloth
            {
              UserId = user.Id,

              Duty = true,

              SlotType = (byte)slotType[x],
              SlotId = slotId[x],
              ClothId = clothId[x]
            };
            context.CharacterClothes.Add(newCloth);
          }
          if (user.GetCharacter().Gender == false)
          {
            CharacterCloth newTorso = new CharacterCloth
            {
              UserId = user.Id,

              Duty = true,

              SlotType = 0,
              SlotId = 3,
              ClothId = context.ClothCombinations.FirstOrDefault(c => c.Top == clothId[1] && c.Gender == character.Gender).Torso
            };
            CharacterCloth newUndershirt = new CharacterCloth
            {
              UserId = user.Id,

              Duty = true,

              SlotType = 0,
              SlotId = 8,
              ClothId = context.ClothCombinations.FirstOrDefault(c => c.Top == clothId[1] && c.Gender == character.Gender).Undershirt
            };
            context.CharacterClothes.Add(newTorso);
            context.CharacterClothes.Add(newUndershirt);
          }
        }
        else
        {
          for (var x = 0; x < slotType.Length; x++)
          {
            var loopCloth = context.CharacterClothes.FirstOrDefault(u => u.UserId == user.Id && u.SlotType == slotType[x] && u.SlotId == slotId[x]);
            loopCloth.ClothId = clothId[x];
          }
          CharacterCloth torso = context.CharacterClothes.FirstOrDefault(u => u.UserId == user.Id && u.SlotType == 0 && u.SlotId == 3);
          CharacterCloth undershirt = context.CharacterClothes.FirstOrDefault(u => u.UserId == user.Id && u.SlotType == 0 && u.SlotId == 8);

          torso.ClothId = context.ClothCombinations.FirstOrDefault(c => c.Top == clothId[1] && c.Gender == character.Gender).Torso;
          undershirt.ClothId = context.ClothCombinations.FirstOrDefault(c => c.Top == clothId[1] && c.Gender == character.Gender).Undershirt;
        }
        context.SaveChanges();
      }
      LoadCharacterDefaults(client);
    }

    [RemoteEvent("defaultCharacterCloth")]
    public static void LoadCharacterDefaults(Player player)
    {
      User user = player.GetUser();
      using (var context = new DatabaseContext())
      {
        List<CharacterCloth> charClothes = context.CharacterClothes.ToList().FindAll(c => c.UserId == user.Id && c.Duty == false);
        player.ClearAccessory(0);
        player.ClearAccessory(1);
        player.ClearAccessory(2);
        player.ClearAccessory(6);
        player.ClearAccessory(7);

        foreach (var cloth in charClothes)
        {
          if (cloth.SlotType == 1)
          {
            player.SetAccessories(cloth.SlotId, cloth.ClothId, 0);
          }
          else
          {
            player.SetClothes(cloth.SlotId, cloth.ClothId, cloth.Texture);
          }
        }
      }
    }

    [RemoteEvent("SERVER:BuyCharacterClothes")]
    public void RmtEvent_BuyClothes(Player client, string type, string jsonData)
    {
      /*
       * [0] ComponentID
       * [1] TextureID
       * [2] ClotheID
       * [3] TorsoID
       * [4] UndershirtID
       * [5] UndershirtTextureID
       * [6] Price
       */
      
      int[] data = JsonConvert.DeserializeObject<int[]>(jsonData);
      User user = client.GetUser();
      if (user.Handmoney < data[6])
      {
        client.TriggerEvent("clothesMenu:Error");
        return;
      }
      
      if (type == "clothe")
      {
        if (data[0] == 11)//for tops
        {
          client.SetClothes(11, data[2], data[1]); //set Top
          client.SetClothes(8, data[4], data[5]); //set undershirt
          client.SetClothes(3, data[3], 0); //set Torso
        }
        else
        {
          client.SetClothes(data[0], data[2], data[1]);
        }
        using (var dbContext = new DatabaseContext())
        {
          
          var clothes = dbContext.CharacterClothes.FirstOrDefault(c => c.UserId == user.Id && c.SlotId == data[0] && c.Duty == false);

          if(clothes == null)
          {
            CharacterCloth newCloth = new CharacterCloth
            {
              UserId = user.Id,

              Duty = false,

              SlotType = 0,
              SlotId = data[0],
              ClothId = data[2],
              Texture = data[1]
            };
            dbContext.CharacterClothes.Add(newCloth);
          }
          else
          {
            clothes.ClothId = data[2];
            clothes.Texture = data[1];
          }
          if(data[0] == 11)
          {
            var torso = dbContext.CharacterClothes.FirstOrDefault(c => c.UserId == user.Id && c.SlotId == 3 && c.Duty == false);
            var undershirt = dbContext.CharacterClothes.FirstOrDefault(c => c.UserId == user.Id && c.SlotId == 8 && c.Duty == false);
            if(torso == null)
            {
              CharacterCloth newTorso = new CharacterCloth
              {
                UserId = user.Id,

                Duty = false,

                SlotType = 0,
                SlotId = 3,
                ClothId = data[3]
              };
              dbContext.CharacterClothes.Add(newTorso);
            }
            else
            {
              torso.ClothId = data[3];
            }
            if(undershirt == null)
            {
              CharacterCloth newUndershirt = new CharacterCloth
              {
                UserId = user.Id,
                Duty = false,
                SlotType = 0,
                SlotId = 8,
                ClothId = data[4],               
                Texture = data[5]
              };
              dbContext.CharacterClothes.Add(newUndershirt);
            }
            else
            {
              undershirt.ClothId = data[4];
              undershirt.Texture = data[5];
            }
          }
          client.GetUser(dbContext).Handmoney -= data[6];
          dbContext.SaveChanges();
          client.TriggerEvent("SERVER:SET_HANDMONEY", user.Handmoney);

        }
        client.TriggerEvent("clothesMenu:updateLast", data[2], data[1], data[4], data[5], data[3]);
      }
    }
  }
}
