using System;
using GTANetworkAPI;
using Newtonsoft.Json.Linq;
using ReallifeGamemode.Server.Types;
using ReallifeGamemode.Server.Common;

namespace ReallifeGamemode.Server.Util
{
  public class VehicleStreaming : Script
  {
    private const string DataKey = "VehicleData";

    public static void SetEngineState(Vehicle veh, bool state)
    {
      var data = GetData(veh);
      data.EngineState = state;
      SetData(veh, data);
    }

    public static bool GetEngineState(Vehicle veh)
    {
      return GetData(veh).EngineState;
    }

    public static void SetLockStatus(Vehicle veh, bool state)
    {
      var data = GetData(veh);
      data.Locked = state;
      SetData(veh, data);
    }

    public static bool GetLockState(Vehicle veh)
    {
      return GetData(veh).Locked;
    }

    public static void SetDoorState(Vehicle veh, DoorID door, DoorState state)
    {
      VehicleData data = GetData(veh);

      data.Doors[(int)door] = (int)state;

      SetData(veh, data);
    }

    public static DoorState GetDoorState(Vehicle veh, DoorID door)
    {
      VehicleData data = GetData(veh);

      if (!data.Doors.ContainsKey((int)door))
      {
        return DoorState.DoorClosed;
      }

      return (DoorState)data.Doors[(int)door];
    }

    public static VehicleData GetData(Vehicle veh)
    {
      if (!veh.HasSharedData(DataKey))
      {
        return new VehicleData();
      }

      return veh.GetSharedData<string>(DataKey).DeserializeJson<VehicleData>();
    }

    public static void SetData(Vehicle veh, VehicleData data)
    {
      if (data is null)
      {
        throw new ArgumentNullException(nameof(data));
      }

      var dataStr = data.SerializeJson();

      veh.SetSharedData(DataKey, dataStr);
      NAPI.ClientEvent.TriggerClientEventForAll("SERVER:Vehicle:UpdateData", veh.Handle.Value, dataStr);
    }

    // INDICATORS

    [RemoteEvent("CLIENT:toggleLeftIndicator")]
    public void ToggleLeftIndicator(Player player)
    {
      if (!player.IsInVehicle || player.VehicleSeat != 0) return;
      Vehicle veh = player.Vehicle;

      if (!(veh.GetData<IndicatorData>("indicatorData") is IndicatorData data)) data = new IndicatorData();

      if (data.Left && data.Right)
      {
        data.Right = false;
      }
      else
      {
        data.Left = !data.Left;
        data.Right = false;
      }

      veh.SetData("indicatorData", data);
      NAPI.ClientEvent.TriggerClientEventForAll("SERVER:setIndicatorStatus", veh.Handle.Value, data.Left, data.Right);
    }

    [RemoteEvent("CLIENT:toggleRightIndicator")]
    public void ToggleRightIndicator(Player player)
    {
      if (!player.IsInVehicle || player.VehicleSeat != 0) return;
      Vehicle veh = player.Vehicle;

      if (!(veh.GetData<IndicatorData>("indicatorData") is IndicatorData data)) data = new IndicatorData();

      if (data.Left && data.Right)
      {
        data.Left = false;
      }
      else
      {
        data.Right = !data.Right;
        data.Left = false;
      }

      veh.SetData("indicatorData", data);
      NAPI.ClientEvent.TriggerClientEventForAll("SERVER:setIndicatorStatus", veh.Handle.Value, data.Left, data.Right);
    }

    [RemoteEvent("CLIENT:toggleWarningIndicator")]
    public void ToggleWarningIndicator(Player player)
    {
      if (!player.IsInVehicle || player.VehicleSeat != 0) return;
      Vehicle veh = player.Vehicle;

      if (!(veh.GetData<IndicatorData>("indicatorData") is IndicatorData data)) data = new IndicatorData();

      if (data.Right && data.Left)
      {
        data.Right = false;
        data.Left = false;
      }
      else
      {
        data.Right = true;
        data.Left = true;
      }

      veh.SetData("indicatorData", data);
      NAPI.ClientEvent.TriggerClientEventForAll("SERVER:setIndicatorStatus", veh.Handle.Value, data.Left, data.Right);
    }
  }
}
