using HarmonyLib;
using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.DreamCandles.Patches;
using QSB.EchoesOfTheEye.DreamObjectProjectors.WorldObject;
using QSB.EchoesOfTheEye.DreamRafts.Messages;
using QSB.EchoesOfTheEye.DreamRafts.WorldObjects;
using QSB.Messaging;
using QSB.Patches;
using QSB.Utility;
using QSB.WorldSync;

namespace QSB.EchoesOfTheEye.DreamRafts.Patches;

public class DreamRaftPatches : QSBPatch
{
	public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;

	[HarmonyPrefix]
	[HarmonyPatch(typeof(DreamRaftProjector), nameof(DreamRaftProjector.RespawnRaft))]
	private static void RespawnRaft_Prefix(DreamRaftProjector __instance)
	{
		if (Remote)
		{
			return;
		}

		if (!QSBWorldSync.AllObjectsReady)
		{
			return;
		}

		__instance.GetWorldObject<QSBDreamObjectProjector>()
			.SendMessage(new RespawnRaftMessage());

		// since respawning extinguishes all the candles, but we already have the above message
		DreamCandlePatches.DontSendMessage = true;
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(DreamRaftProjector), nameof(DreamRaftProjector.RespawnRaft))]
	private static void RespawnRaft_Postfix(DreamRaftProjector __instance)
	{
		if (Remote)
		{
			return;
		}

		if (!QSBWorldSync.AllObjectsReady)
		{
			return;
		}

		DreamCandlePatches.DontSendMessage = false;
	}

	/// <summary>
	/// this is only called when:
	///	- you exit the dream world
	/// - the raft goes thru the warp volume with you not on it
	///
	/// this is to suspend the raft so it doesn't fall endlessly.
	/// however, it's okay if it does that,
	/// and we don't want it to extinguish with other players on it.
	/// </summary>
	[HarmonyPrefix]
	[HarmonyPatch(typeof(DreamRaftProjector), nameof(DreamRaftProjector.ExtinguishImmediately))]
	private static bool ExtinguishImmediately(DreamRaftProjector __instance)
	{
		if (!QSBWorldSync.AllObjectsReady)
		{
			return true;
		}

		// still release authority over the raft tho
		__instance._dreamRaftProjection.GetWorldObject<QSBDreamRaft>()
			.NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Remove);

		return false;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(DreamRaftProjection), nameof(DreamRaftProjection.UpdateVisibility))]
	private static void UpdateVisibility(DreamRaftProjection __instance, bool immediate = false) =>
		DebugLog.DebugWrite($"DreamRaftProjection.UpdateVisibility | {__instance._visible} | {immediate} | {Remote}");
}