using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using GTANetworkAPI;
using ReallifeGamemode.Database.Entities;
using ReallifeGamemode.Database.Models;
using ReallifeGamemode.Server.Extensions;
using ReallifeGamemode.Server.Job;
using ReallifeGamemode.Server.Managers;
using ReallifeGamemode.Server.Util;
using ReallifeGamemode.Services;
using ReallifeGamemode.Server.Services;
using ReallifeGamemode.Server.Types;
using ReallifeGamemode.Server.Report;
using ReallifeGamemode.Server.Factions.Medic;
using ReallifeGamemode.Server.Inventory.Interfaces;
using ReallifeGamemode.Server.Inventory;
using ReallifeGamemode.Database.Entities.Logs;

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

namespace ReallifeGamemode.Server.Events
{
  public class Disconnect : Script
  {
    [ServerEvent(Event.PlayerDisconnected)]
    public void OnPlayerDisconnected(Player player, DisconnectionType type, string reason)
    {
      if (!player.IsLoggedIn()) return;
      using var saveUser = new DatabaseContext();
      User user = player.GetUser(saveUser);

      if (user == null)
      {
        return;
      }

      var logEntry = new LoginLogoutLogEntry()
      {
        LoginLogout = false,
        User = user,
        PlayerId = player.Handle.Value,
        Username = player.Name,
        SocialClubName = player.SocialClubName,
        IpAddress = player.Address,
        Time = DateTime.Now,
      };

      saveUser.LoginLogoutLogs.Add(logEntry);

      if (type == DisconnectionType.Left)
      {
        NAPI.Util.ConsoleOutput(player.Name + " left");
      }
      if (type == DisconnectionType.Kicked)
      {
        NAPI.Util.ConsoleOutput(player.Name + " kicked");
      }
      if (type == DisconnectionType.Timeout)
      {
        NAPI.Util.ConsoleOutput(player.Name + " timed out");
      }

      /*if (GlobalHelper.DutyAdmins.Contains(player))
      {
        GlobalHelper.DutyAdmins.Remove(player);
      }*/

      if (user.IsAdmin(AdminLevel.MAPPING))
      {
        ChatService.BroadcastAdmin("!{#FFFF00}*** " + player.Name + " hat den Server verlassen", AdminLevel.MAPPING);
      }

      MedicTask task = Medic.ReviveTasks.FirstOrDefault(t => t.Victim == player.Name);

      if (task != null)
      {
        ChatService.BroadcastFaction("~y~[MEDIC] ~w~Info: Der Auftrag von " + player.Name + " wurde entfernt (Ausgeloggt)", new List<int>() { 2 });
      }

      if (player.IsAdminDuty())
      {
        ChatService.Broadcast("!{#ee4d2e}[SUPPORT] " + player.Name + " hat sich vom Support abgemeldet (Ausgeloggt)");
      }

      /*
      TaxiDriverJob taxiJob = JobManager.GetJob<TaxiDriverJob>();
      TaxiContract taxiContract = taxiJob.TaxiContracts.Where(t => t.Name == player.Name).FirstOrDefault();

      if (taxiContract != null)
      {
        if (taxiJob.TaxiContracts.Contains(taxiContract))
        {
          taxiJob.TaxiContracts.Remove(taxiContract);
        }
      }
      */
      ReportManage temp;
      for (int a = 0; a < Report.Report.listReports.Count; a++)
      {
        temp = Report.Report.listReports[a];

        if (temp.getAdmin().Equals(player.Name))
        {
          Report.Report.listReports.Remove(temp);

          Player ticketUser = PlayerService.GetPlayerByNameOrId(temp.getUser());
          ticketUser.SendChatMessage("!{#008fff}[REPORT]!{#FFFFFF} Chat beendet. Der Admin hat den Server verlassen");
          break;
        }

        if (temp.getUser().Equals(player.Name))
        {
          Player admin = PlayerService.GetPlayerByNameOrId(temp.getAdmin());
          if (admin != null)
          {
            admin.SendChatMessage("!{#008fff}[REPORT]!{#FFFFFF} Chat beendet. Der User hat den Server verlassen");
          }
          Report.Report.listReports.Remove(temp);
          break;
        }
      }

      if (Rentcar.mapPlayerRentcarBill.ContainsKey(player.Name))
      {
        Rentcar.cancelRent(player);
      }

      //Vehicle LastVehicle = player.GetData<Vehicle>("LastVehicle");
      JobBase job = JobManager.GetJob(player.GetUser().JobId ?? -1);
      if (job != null)
      {
        if (job.GetUsersInJob().Contains(player))
        {
          if (player.Vehicle != null)
          {
            //if (player.Vehicle.GetData<bool>("timerJobVehicleRespawn") == true)
            //{
            if (player.Vehicle.GetServerVehicle() is JobVehicle vehJ && job.Id == JobManager.GetJob<RefuseCollectorJob>().Id)
            {
              player.Vehicle.ResetData("timerJobVehicleRespawn");
              ServerVehicle sVeh = VehicleManager.GetServerVehicleFromVehicle(player.Vehicle);
              ServerVehicleExtensions.Spawn(sVeh, player.Vehicle);
            }
            //}
          }
          if (Managers.JobManager.playerTimersJobVehicleRespawn.ContainsKey(player))
          {
            Managers.JobManager.playerTimersJobVehicleRespawn[player].Stop();
          }
          player.ResetData("PilotenBase");
          job.StopJob(player);
          ChatService.SendMessage(player, $"~y~[JOB]~s~ Du hast deinen Job ~o~{job.Name}~s~ beendet.");
          if (player.GetData<bool>("HatRoute") == true)
          {
            CheckPointHandle.DeleteCheckpoints(player);
            player.ResetData("HatRoute");
          }
        }
      }

      List<UserItem> fItem = saveUser.UserItems.Where(u => u.UserId == user.Id).ToList();

      foreach (var item in fItem)
      {
        IItem iItem = InventoryManager.GetItemById(item.ItemId);
        if (iItem is IWeaponDealItem obj)
        {
          int amount = item.Amount;

          Vector3 dropPosition = PlayerExtension.GetPositionFromPlayer(player, 0.6f, 0);
          //new Vector3(player.Position.X, player.Position.Y, player.Position.Z - 0.8f);
          Random r = new Random();
          GTANetworkAPI.Object grndObject;
          Vector3 textPos = dropPosition;

          dropPosition.Z -= 1.05f;
          grndObject = NAPI.Object.CreateObject(3666746839, dropPosition, new Vector3(0, 0, r.Next(0, 360)), 255, 0);

          GroundItem grndItem = new GroundItem { ItemId = iItem.Id, Amount = amount, Position = dropPosition };
          TextLabel grndTxtLbl = NAPI.TextLabel.CreateTextLabel(iItem.Name + " ~s~(~y~" + amount + "~s~)", textPos, 5, 0.5f, 4, new Color(255, 255, 255), false, 0);
          GroundItem.AddGroundItem(grndItem, grndObject, grndTxtLbl);

          saveUser.Remove(item);
        }
      }

      Vector3 pos = player.Position;

      user.PositionX = pos.X;
      user.PositionY = pos.Y;
      user.PositionZ = pos.Z;
      saveUser.SaveChanges();
      user.Dead = player.HasData("isDead") ? (bool)player.GetData<bool>("isDead") : false;

      if (user.Wanteds > 0)
      {
        ChatService.HQMessage("Der Straftäter " + user.Name + " ist vom Radar verschwunden");
      }

      player.SetData("isLoggedIn", false);
      player.TriggerEvent("CLIENT:DestroyPed", 1);
      player.TriggerEvent("CLIENT:DestroyPed", 2);
      player.TriggerEvent("CLIENT:DestroyPed", 3);
      player.TriggerEvent("CLIENT:DestroyPed", 4);

      Medic.delHealTask(player);
      Medic.delReviveTask(player);
      if (player.GetData<bool>("duty") == true)
      {
        player.SetData<bool>("duty", false);
        Medic.UpdateDutyMedics();
      }
    }
  }
}
