using RimWorld;
using System.Collections.Generic;
using System.Linq;
using Verse;
using System;

namespace rjw.RMB
{
	/// <summary>
	/// Generator of RMB categories for rape
	/// </summary>
	static class RMB_Rape
	{
		/// <summary>
		/// Add rape and reverse rape options to <paramref name="opts"/>
		/// </summary>
		/// <param name="pawn">Selected pawn</param>
		/// <param name="opts">List of RMB options</param>
		/// <param name="target">Target of the right click</param>
		public static void AddFloatMenuOptions(Pawn pawn, List<FloatMenuOption> opts, LocalTargetInfo target)
		{
			AcceptanceReport canCreateEntries = DoBasicChecks(pawn, target.Pawn);

			if (!canCreateEntries)
			{
				if (RJWSettings.DevMode && !canCreateEntries.Reason.NullOrEmpty())
					opts.Add(new FloatMenuOption(canCreateEntries.Reason, null));

				return;
			}

			canCreateEntries = DoChecks(pawn, target.Pawn);

			if (!canCreateEntries)
			{
				opts.Add(new FloatMenuOption("RJW_RMB_Rape".Translate(target.Pawn) + ": " + canCreateEntries.Reason, null));
				return;
			}

			FloatMenuOption opt = GenerateCategoryOption(pawn, target);
			if (opt != null)
				opts.Add(opt);

			opt = GenerateCategoryOption(pawn, target, true);
			if (opt != null)
				opts.Add(opt);
		}

		/// <summary>
		/// Check for the things that should be obvious to the player or does not change for particular pawns.
		/// </summary>
		/// <returns>
		/// AcceptanceReport. Reason is an untranslated string and should only be shown in the DevMode
		/// </returns>
		private static AcceptanceReport DoBasicChecks(Pawn pawn, Pawn target)
		{
			if (!RJWSettings.rape_enabled)
			{
				return "No rape: Disabled by the mod settings";
			}

			if (!xxx.can_rape(pawn, true))
			{
				return "No rape: Pawn can't rape";
			}

			if (!xxx.can_be_fucked(target))
			{
				return "No rape: Target can't have sex";
			}

			if (target.HostileTo(pawn) && !target.Downed)
			{
				return "No rape: Hostile must be downed";
			}

			return true;
		}

		/// <summary>
		/// Check for the things that can change for particular pawns.
		/// </summary>
		/// <returns>
		/// AcceptanceReport. Reason is a translated string and should not be null.
		/// </returns>
		private static AcceptanceReport DoChecks(Pawn pawn, Pawn target)
		{
			if (!pawn.IsDesignatedHero() && !pawn.IsHeroOwner())
			{
				if (SexAppraiser.would_fuck(pawn, target) < 0.1f)
					return "RJW_RMB_ReasonUnappealingTarget".Translate();
			}

			return true;
		}

		/// <summary>
		/// Generate one FloatMenuOption
		/// </summary>
		/// <param name="pawn"></param>
		/// <param name="target"></param>
		/// <param name="reverse"></param>
		/// <returns>Category-level item that opens a sub-menu on click</returns>
		private static FloatMenuOption GenerateCategoryOption(Pawn pawn, LocalTargetInfo target, bool reverse = false)
		{
			string text = null;

			if (reverse)
			{
				text = "RJW_RMB_Rape_Reverse".Translate(target.Pawn);
			}
			else
			{
				text = "RJW_RMB_Rape".Translate(target.Pawn);
			}

			Action action = null;

			if (target.Pawn.HostileTo(pawn))
			{
				action = delegate ()
				{
					JobDef job = xxx.RapeEnemy;
					var validinteractions = RMB_Menu.GenerateNonSoloSexRoleOptions(pawn, target, job, true, reverse);
					if (validinteractions.Any())
						FloatMenuUtility.MakeMenu(validinteractions, (FloatMenuOption opt) => opt.Label, (FloatMenuOption opt) => opt.action);
					else
						Messages.Message("No valid interactions found for " + text, MessageTypeDefOf.RejectInput, false);
				};
			}
			else if (target.Pawn.IsDesignatedComfort())
			{
				action = delegate ()
				{
					JobDef job = xxx.RapeCP;
					var validinteractions = RMB_Menu.GenerateNonSoloSexRoleOptions(pawn, target, job, true, reverse);
					if (validinteractions.Any())
						FloatMenuUtility.MakeMenu(validinteractions, (FloatMenuOption opt) => opt.Label, (FloatMenuOption opt) => opt.action);
					else
						Messages.Message("No valid interactions found for " + text, MessageTypeDefOf.RejectInput, false);
				};
			}
			else if (xxx.can_get_raped(target.Pawn) && (xxx.get_vulnerability(target.Pawn) >= xxx.get_vulnerability(pawn)))
			{
				action = delegate ()
				{
					JobDef job = xxx.RapeRandom;
					var validinteractions = RMB_Menu.GenerateNonSoloSexRoleOptions(pawn, target, job, true, reverse);
					if (validinteractions.Any())
						FloatMenuUtility.MakeMenu(validinteractions, (FloatMenuOption opt) => opt.Label, (FloatMenuOption opt) => opt.action);
					else
						Messages.Message("No valid interactions found for " + text, MessageTypeDefOf.RejectInput, false);
				};
			}
			else
			{
				if (RJWSettings.DevMode && !reverse)
				{
					return new FloatMenuOption("No rape: Target not hostile, not CP, can't be raped, or not vulnerable enough", null);
				}

				return null;
			}

			return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text, action, MenuOptionPriority.High), pawn, target);
		}
	}
}
