using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.Command;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking;
using Dalamud.IoC;
using Dalamud.Logging;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Component.GUI;
using Newtonsoft.Json;

namespace CrystallineConflictWinsTracker;

public sealed class Plugin : IDalamudPlugin, IDisposable
{
	private unsafe delegate void* AgentShow(void* a1);

	private unsafe delegate void* FireCallbackDelegate(AtkUnitBase* atkUnitBase, int valueCount, AtkValue* atkValues, ulong a4);

	private const string commandName = "/ccwins";

	public bool dutyFinderVisible;

	public bool pvpPageVisible;

	public bool casualCCEnabled;

	public bool rankedCCEnabled;

	public bool alertedDebugWindow;

	private Hook<FireCallbackDelegate> addonReceiveEventHook;

	public string Name => "Crystaline Conflict Winratio tracker";

	private DalamudPluginInterface PluginInterface { get; init; }

	private ICommandManager CommandManager { get; init; }

	private Configuration Configuration { get; init; }

	private PluginUI PluginUi { get; init; }

	public long rcStartTime { get; private set; }

	private Hook<AgentShow> DutyFinderHook { get; set; }

	public unsafe AtkUnitBase* dutyFinderAtkUnitBase { get; private set; }

	public string DataPath { get; }

	public Plugin([RequiredVersion("1.0")] DalamudPluginInterface pluginInterface)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Expected O, but got Unknown
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Expected O, but got Unknown
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Expected O, but got Unknown
		DalamudApi.Initialize(pluginInterface);
		DalamudApi.PluginLog.Debug("Initializing the plugin...", Array.Empty<object>());
		PluginInterface = pluginInterface;
		CommandManager = DalamudApi.CommandManager;
		DalamudApi.Framework.Update += new OnUpdateDelegate(Framework_UpdateNew);
		Configuration = (PluginInterface.GetPluginConfig() as Configuration) ?? new Configuration();
		Configuration.Initialize(PluginInterface);
		DataPath = PluginInterface.ConfigDirectory?.ToString() + "/data/";
		try
		{
			Directory.CreateDirectory(DataPath);
		}
		catch (Exception ex)
		{
			PluginLog.LogError(ex, "Failed to create data directory.", Array.Empty<object>());
		}
		if (!File.Exists(DataPath + "pvpstats.json"))
		{
			File.Create(DataPath + "pvpstats.json");
		}
		PluginUi = new PluginUI(Configuration, DataPath);
		DalamudApi.CommandManager.AddHandler("/ccwins", new CommandInfo(new HandlerDelegate(OnCommand))
		{
			HelpMessage = "Show the tracker UI"
		});
		PluginInterface.UiBuilder.Draw += DrawUI;
		PluginInterface.UiBuilder.OpenConfigUi += DrawConfigUI;
		DalamudApi.ClientState.EnterPvP += ClientState_EnterPvP;
		DalamudApi.ClientState.LeavePvP += ClientState_LeavePvP;
		DalamudApi.ChatGui.ChatMessage += new OnMessageDelegate(Chat_ChatMessage);
	}

	private void Framework_UpdateNew(IFramework framework)
	{
		if (Configuration.Enabled && DalamudApi.ClientState.IsLoggedIn)
		{
			CheckForDfSelections();
		}
	}

	private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Invalid comparison between Unknown and I4
		if ((int)type != 2112)
		{
			return;
		}
		PluginLog.Debug(message.TextValue, Array.Empty<object>());
		if (message.TextValue.Contains("900 Series EXP."))
		{
			PluginLog.Debug("WE WON THE GAME?", Array.Empty<object>());
			if (casualCCEnabled)
			{
				PluginLog.Debug("CASUAL WIN", Array.Empty<object>());
				StoreNewPvpRow(ranked: false, win: true);
			}
			else if (rankedCCEnabled)
			{
				PluginLog.Debug("RANKED WIN", Array.Empty<object>());
				StoreNewPvpRow(ranked: true, win: true);
			}
			else
			{
				PluginLog.Error("NEITHER MODE IS UP? WAT?", Array.Empty<object>());
			}
		}
		else if (message.TextValue.Contains("700 Series EXP."))
		{
			PluginLog.Debug("WE LOST THE GAME?", Array.Empty<object>());
			if (casualCCEnabled)
			{
				PluginLog.Debug("CASUAL LOSS", Array.Empty<object>());
				StoreNewPvpRow(ranked: false, win: false);
			}
			else if (rankedCCEnabled)
			{
				PluginLog.Debug("RANKED LOSS", Array.Empty<object>());
				StoreNewPvpRow(ranked: true, win: false);
			}
			else
			{
				PluginLog.Error("NEITHER MODE IS UP? WAT?", Array.Empty<object>());
			}
		}
	}

	private void StoreNewPvpRow(bool ranked, bool win)
	{
		string text = File.ReadAllText(DataPath + "pvpstats.json");
		List<PvpWinEntry> obj = JsonConvert.DeserializeObject<List<PvpWinEntry>>(text) ?? new List<PvpWinEntry>();
		obj.Add(new PvpWinEntry
		{
			classId = ((Character)DalamudApi.ClientState.LocalPlayer).ClassJob.Id,
			win = win,
			ranked = ranked,
			className = ((Character)DalamudApi.ClientState.LocalPlayer).ClassJob.GameData.Name.RawString,
			matchDate = DateTime.Now
		});
		text = JsonConvert.SerializeObject((object)obj);
		File.WriteAllText(DataPath + "pvpstats.json", text);
	}

	private void ClientState_LeavePvP()
	{
		PluginLog.Debug("Yes, we left pvp :)", Array.Empty<object>());
	}

	private unsafe void* CallbackDetour(AtkUnitBase* atkunitbase, int valuecount, AtkValue* atkvalues, ulong a4)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Expected I4, but got Unknown
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Invalid comparison between Unknown and I4
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Invalid comparison between Unknown and I4
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Invalid comparison between Unknown and I4
		if (dutyFinderAtkUnitBase == null)
		{
			return addonReceiveEventHook.Original(atkunitbase, valuecount, atkvalues, a4);
		}
		if (atkunitbase == dutyFinderAtkUnitBase)
		{
			PluginLog.Debug("OMG ITS CONTENTSFINDER :D", Array.Empty<object>());
			List<object> list = new List<object>();
			List<ValueType> list2 = new List<ValueType>();
			try
			{
				AtkValue* ptr = atkvalues;
				for (int i = 0; i < valuecount; i++)
				{
					list2.Add(((AtkValue)ptr).Type);
					ValueType type = ((AtkValue)ptr).Type;
					switch (type - 2)
					{
					case 0:
						list.Add(((AtkValue)ptr).Byte > 0);
						break;
					case 1:
						list.Add(((AtkValue)ptr).Int);
						break;
					case 2:
						list.Add(((AtkValue)ptr).UInt);
						break;
					case 4:
						list.Add(Marshal.PtrToStringUTF8(new IntPtr(((AtkValue)ptr).String)));
						break;
					default:
						list.Add($"Unknown Type: {((AtkValue)ptr).Type}");
						break;
					}
					ptr = (AtkValue*)((byte*)ptr + Unsafe.SizeOf<AtkValue>());
				}
			}
			catch
			{
				return addonReceiveEventHook.Original(atkunitbase, valuecount, atkvalues, a4);
			}
			if (valuecount > 1)
			{
				object obj2 = list[1];
				ValueType val = list2[1];
				if ((int)val == 3)
				{
					if ((int)obj2 == 8)
					{
						PluginLog.Debug("HOOO BOY WE GOING PVP", Array.Empty<object>());
						pvpPageVisible = true;
					}
					else
					{
						pvpPageVisible = false;
					}
				}
				else if ((int)val == 4 && (int)list2[0] == 3 && (int)list[0] == 3)
				{
					PluginLog.Debug("SOMETHIGNG CLICKED?", Array.Empty<object>());
					if (pvpPageVisible)
					{
						AtkComponentCheckBox* nodeById = (AtkComponentCheckBox*)((AtkUnitBase)(nint)DalamudApi.GameGui.GetAddonByName("ContentsFinder", 1)).GetNodeById(4u);
						AtkComponentCheckBox* ptr2 = (AtkComponentCheckBox*)2267615832848uL;
						if ((uint)list[1] == 1)
						{
							PluginLog.Debug("FUCKING CASUAL :D", Array.Empty<object>());
						}
						else if ((uint)list[1] == 2)
						{
							PluginLog.Debug("FUCKING HARDCORE RANKED :D", Array.Empty<object>());
						}
					}
				}
			}
		}
		return addonReceiveEventHook.Original(atkunitbase, valuecount, atkvalues, a4);
	}

	private void ClientState_EnterPvP()
	{
		PluginLog.Debug("Yes, we entered pvp :)", Array.Empty<object>());
	}

	private unsafe void InstallAddonReceiveEventHook()
	{
		string text = "E8 ?? ?? ?? ?? 8B 4C 24 20 0F B6 D8";
		nint num = DalamudApi.SigScanner.ScanText(text);
		addonReceiveEventHook = DalamudApi.Hooks.HookFromAddress<FireCallbackDelegate>((IntPtr)num, (FireCallbackDelegate)CallbackDetour, (HookBackend)0);
	}

	private unsafe AtkUnitBase* GetDutyFinderPointer()
	{
		nint addonByName = DalamudApi.GameGui.GetAddonByName("ContentsFinder", 1);
		if (addonByName != IntPtr.Zero)
		{
			AtkUnitBase* ptr = (AtkUnitBase*)addonByName;
			if (((AtkUnitBase)ptr).RootNode != null)
			{
				return ptr;
			}
			return null;
		}
		return null;
	}

	private void Framework_Update(IFramework framework)
	{
		if (Configuration.Enabled && DalamudApi.ClientState.IsLoggedIn)
		{
			CheckForDfSelections();
		}
	}

	private unsafe void CheckForDfSelections()
	{
		nint addonByName = DalamudApi.GameGui.GetAddonByName("ContentsFinderConfirm", 1);
		AtkUnitBase* ptr = (AtkUnitBase*)addonByName;
		if (ptr != null && ((AtkUnitBase)ptr).IsVisible)
		{
			AtkTextNode* nodeById = (AtkTextNode*)((AtkUnitBase)ptr).GetNodeById(49u);
			if (nodeById != null && ((Utf8String)(&((AtkTextNode)nodeById).NodeText)).StringPtr != null)
			{
				string text = Marshal.PtrToStringUTF8(new IntPtr(((Utf8String)(&((AtkTextNode)nodeById).NodeText)).StringPtr));
				if (text != null)
				{
					if (text.Contains("Crystalline Conflict (Casual Match)"))
					{
						if (!casualCCEnabled)
						{
							casualCCEnabled = true;
							rankedCCEnabled = false;
							PluginLog.Debug("CASUAL CC MATCH INCOMING, SETTING TRUE", Array.Empty<object>());
						}
					}
					else if (text.Contains("Crystalline Conflict (Ranked Match)") && !rankedCCEnabled)
					{
						rankedCCEnabled = true;
						casualCCEnabled = false;
						PluginLog.Debug("RANKED CC MATCH INCOMING, SETTING TRUE", Array.Empty<object>());
					}
				}
			}
		}
		nint addonByName2 = DalamudApi.GameGui.GetAddonByName("ContentsFinder", 1);
		if (addonByName2 != IntPtr.Zero)
		{
			AtkUnitBase* ptr2 = (dutyFinderAtkUnitBase = (AtkUnitBase*)addonByName2);
			if (((AtkUnitBase)ptr2).RootNode != null && ((AtkUnitBase)ptr2).IsVisible)
			{
				dutyFinderVisible = true;
			}
		}
	}

	public void Dispose()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Expected O, but got Unknown
		PluginUi.Dispose();
		DalamudApi.CommandManager.RemoveHandler("/ccwins");
		DalamudApi.Framework.Update -= new OnUpdateDelegate(Framework_Update);
		DalamudApi.ClientState.LeavePvP -= ClientState_LeavePvP;
		DalamudApi.ClientState.EnterPvP -= ClientState_EnterPvP;
		DalamudApi.ChatGui.ChatMessage -= new OnMessageDelegate(Chat_ChatMessage);
	}

	private void OnCommand(string command, string args)
	{
		PluginUi.Visible = true;
	}

	private void DrawUI()
	{
		PluginUi.Draw();
	}

	private void DrawConfigUI()
	{
		PluginUi.SettingsVisible = true;
	}
}
