using System.Globalization;
using GTANetworkAPI;
using Newtonsoft.Json;
using ReallifeGamemode.Server.Classes;
using ReallifeGamemode.Server.Finance;
using ReallifeGamemode.Server.Managers;
using ReallifeGamemode.Server.Util;
using ReallifeGamemode.Server.Wanted;
using ReallifeGamemode.Server.DrivingSchool;
using ReallifeGamemode.Server.WeaponDeal;
using ReallifeGamemode.Server.Core.API;
using ReallifeGamemode.Server.Core.RageMP;
using ReallifeGamemode.Server.Core.Events;
using System.Collections.Generic;
using ReallifeGamemode.Server.Common;
using System.Reflection;
using System.Linq;
using ReallifeGamemode.Server.Job;
using ReallifeGamemode.Database.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ReallifeGamemode.Database.Entities;
using ReallifeGamemode.Services;

/**
* @overview Life of German Reallife - Main Class (Main.cs)
* @author VegaZ, hydrant
* @copyright (c) 2008 - 2018 Life of German
*/

namespace ReallifeGamemode.Server
{
  public class Main : Script
  {
    public static readonly Vector3 DEFAULT_SPAWN_POSITION = new Vector3(-427.5189, 1116.453, 326.7829);
    public static readonly float DEFAULT_SPAWN_HEADING = 340.8f;

    public static readonly CultureInfo SERVER_CULTURE = new CultureInfo("de-DE");

    private EventHandler eventHandler;

    [ServerEvent(Event.ResourceStart)]
    public void OnResourceStart()
    {
      var methods = Assembly.GetExecutingAssembly()
                      .GetTypes()
                      .SelectMany(t => t.GetMethods())
                      .Where(m => m.GetCustomAttributes(typeof(CommandAttribute), false).Length > 0)
                      .ToArray();

      var cmdAttributes = methods.Select(c => c.GetCustomAttribute<CommandAttribute>()).ToList();

      var registeredCommands = cmdAttributes.Select(c => c.CommandString).ToList();
      cmdAttributes.Where(c => c.Alias?.Any() ?? false).ToList().ForEach(a =>
      {
        registeredCommands.AddRange(a.Alias.Split(','));
      });

      IAPI apiInstance = new RageAPI();
      eventHandler = new EventHandler(apiInstance);

      new Core.Main(apiInstance, eventHandler, registeredCommands.ToArray());

      NAPI.Server.SetGlobalServerChat(false);

      NAPI.Server.SetCommandErrorMessage("~r~[FEHLER]~s~ Dieser Command existiert nicht.");
      NAPI.Server.SetDefaultSpawnLocation(DEFAULT_SPAWN_POSITION, DEFAULT_SPAWN_HEADING);
      NAPI.Server.SetAutoSpawnOnConnect(false);
      NAPI.Server.SetAutoRespawnAfterDeath(false);
      NAPI.Data.SetWorldData("playerCreatorDimension", 0);

      JsonConvert.DefaultSettings = () =>
      {
        return new JsonSerializerSettings()
        {
          NullValueHandling = NullValueHandling.Ignore
        };
      };

      InventoryManager.LoadItems();
      ShopManager.LoadClotheShops();
      ShopManager.LoadItemShops();
      TuningManager.LoadTuningGarages();

      TimeManager.StartTimeManager();
      VehicleManager.StartTimer();

      DatabaseHelper.InitDatabaseFirstTime();

      FactionHelper.CheckFactionBankAccounts();
      BusinessManager.LoadBusinesses();
      InteriorManager.LoadInteriors();
      DoorManager.LoadDoors();
      ATMManager.InitATMs();
      CityHallManager.LoadCityHall();
      JobManager.LoadJobs();
      TaxiDriverJob.StartTaxiTimer();
      HouseManager.LoadHouses();
      DrivingSchool.DrivingSchool.Setup();
      PlaneSchool.Setup();
      Gangwar.Gangwar.loadTurfs();

      TempBlip tempBlip = new TempBlip()
      {
        Color = 1,
        Name = "",
        Transparency = 0,
        ShortRange = true,
        Sprite = 1,
        Scale = 1,
      };

      NAPI.Data.SetWorldData("blipTemplate", tempBlip);

      WantedEscapeTimer.WantedTimer();
      Jail.JailTimer();
      Economy.PaydayTimer();
      WeaponDealManager.WeaponDealTimer();

      UserBankAccount.BalanceChanged += (account) =>
      {
        using (var dbContext = new DatabaseContext())
        {
          var user = dbContext.Users.Where(u => u.BankAccountId == account.Id).Select(u => u.Name).FirstOrDefault();
          if (user == null) return;
          PlayerService.GetPlayerByNameOrId(user).TriggerEvent("updateMoney", account.Balance);
        }
      };
    }

    [RemoteEvent("CLIENT:Event")]
    public void OnClientEvent(Player player, string dataStr)
    {
      var data = dataStr.DeserializeJson<List<object>>();
      eventHandler.HandleEvent(new RagePlayer(player), data);
    }
  }
}
