--- Handles asking for sex with players and NPCs
-- @author QueuedResonance 2022, SolarEdge 2024

ZLMain = {};

local ZomboWin = require("ZomboWin/ZomboWin")
local ZomboWinActType = ZomboWinActType

local ISWorldObjectContextMenu = ISWorldObjectContextMenu
local ISContextMenu = ISContextMenu
local ISToolTip = ISToolTip

zwEXP = false;
if getActivatedMods():contains("ZomboWinDefeatStrip") == true then
	zwEXP = true;
	require("ZomboWinDefeatStrip/ZombieHandler");
end
require("ZomboWin/Temptation");

local getText = getText
local string = string

zlmSolo = true;

if getActivatedMods():contains("Bandits") == true then
	require("Bandits/BanditUpdate");
end

local ListedPositions = { --- Add more if there will be more context menu options
	"Oral",
	"Intercourse",
	"Consent",
}

local mastPos = {
	"Quick", "Regular", "Relaxed",
}

local clothingHandler = {};
clothingHandler.checkPants = {"Underwear","UnderwearBottom","Pants","FullSuit",};

local pantsOnlyHandler = {};
pantsOnlyHandler.checkPants = {"Pants",};

function isWearingPants()
    local pp = getPlayer()
    local myClothes = pp:getWornItems()
    if myClothes then
        for i = myClothes:size(), 1, -1 do
            local wornItem = myClothes:get(i - 1)

            if wornItem then
                local item = wornItem:getItem()
                local location = wornItem:getLocation()
                if item:IsClothing() then
                    for v = 1, #pantsOnlyHandler.checkPants do
                        local bodyPart = pantsOnlyHandler.checkPants[v]

                        if location == bodyPart then
                            return true
                        end
                    end
                end
            end
        end
    end

    return false
end

function isSoloPlay(bool)
	zlmSolo = bool;
end
--- Activates when the player clicks ask for seks on the chosen target
-- @worldobjects table of world objects nearby the player
-- @param ContextMenu object injected from ZomboWinContextMenu, can access ZomboWin functionalities with this
-- @param IsoPlayer object of the player
-- @param IsoPlayer object of the asked target
local function onAskForSex(worldobjects, contextMenu, position, requestor, target)
	local isMainHeroFemale = requestor:isFemale()
	local isTargetFemale = target:isFemale()
	local sPosition = ListedPositions[position]
	local maleCount, femaleCount = 0, 0

	if isMainHeroFemale and isTargetFemale then
		--- Lesbian
		maleCount = 0
		femaleCount = 2
	elseif isMainHeroFemale == false and isTargetFemale == false then
		--- Gay
		maleCount = 2
		femaleCount = 0
	else
		--- Straight
		maleCount = 1
		femaleCount = 1
	end

	--- Choose random animation as a test
	--temp check to see if m2m since no aminations 
	if maleCount ~= 2 and femaleCount ~= 2 then
	local animationList = contextMenu.Client.AnimationUtils:getAnimations(2, maleCount, femaleCount, {sPosition})
	local index = ZombRand(1, #animationList + 1)
	local chosenAnimation = animationList[index]
	
	isSoloPlay(false);
	contextMenu.Client.AnimationHandler.Play(worldobjects, {requestor, target}, chosenAnimation, true, true, true)
	end
end

local function onDefeatForSex(worldobjects, contextMenu, position, requestor, target)
	local isMainHeroFemale = requestor:isFemale()
	local isTargetFemale = target:isFemale()
	local sPosition = ListedPositions[position]
	local maleCount, femaleCount = 0, 0

	if isMainHeroFemale and isTargetFemale then
		--- Lesbian
		maleCount = 0
		femaleCount = 2
	elseif isMainHeroFemale == false and isTargetFemale == false then
		--- Gay
		maleCount = 2
		femaleCount = 0
	else
		--- Straight
		maleCount = 1
		femaleCount = 1
	end

	--- Choose random animation as a test
	--temp check to see if m2m since no aminations 
	if maleCount ~= 2 and femaleCount ~= 2 then
		local animationList = contextMenu.Client.AnimationUtils:getAnimations(2, maleCount, femaleCount, {sPosition})
		local index = ZombRand(1, #animationList + 1)
		local chosenAnimation = animationList[index]
		local dummy = ZomboWin.ZombieHandler:convertZombieToSurvivor(target)
		dummy:getModData().dontDefeat = true
		
		isSoloPlay(false);
		local isBandit = target:getVariableBoolean("Bandit");
		playAnim(target, dummy, requestor, chosenAnimation, isBandit); --- works but causes errors
	end
end

local function onSubdue(worldobjects, contextMenu, position, requestor, target)
	HaloTextHelper.addText(requestor, getText("ContextMenu_Subdue_Yes"), HaloTextHelper.getColorGreen());
	--target:setAsSurvivor();
	target:getModData().isSubdued = true;	--- separate action will be performed to subdue.
	local isBandit = target:getVariableBoolean("Bandit");
	if isBandit then
		Bandit.ClearTasks(target);
        Bandit.Say(target, "DEAD");
		target:getModData().wasSubdued = true;
	end
end

local function onRelease(worldobjects, contextMenu, position, requestor, target)
	local isBandit = target:getVariableBoolean("Bandit");
	HaloTextHelper.addText(requestor, getText("ContextMenu_Subdue_Released"), HaloTextHelper.getColorRed());
	target:getModData().isSubdued = false;
	target:setCanWalk(true);
	target:setUseless(false);
	if not target:isSitAgainstWall() then target:setSitAgainstWall(true); end	--- gives player time to run away!
	if isBandit then
		--print("a bandit is released");
		if not Bandit.IsHostile(target) then 
			--- codes here...
			local function makeHostile(target)
				Bandit.SetHostile(target, true); 
				Bandit.Say(target, "SPOTTED");
			end
			
			local chance = (ZomboWinConfig.ModOptions.options.dropdown1);
			
			if chance == 3 then
				makeHostile(target);
			end
			
			if chance == 2 then
				local hostile = ZombRand(2);
				if hostile == 1 then
					makeHostile(target);
				end
			end
		end 
		if Bandit.IsForceStationary(target) then Bandit.ForceStationary(target, false); end
		--if not target:isSitAgainstWall() then target:setSitAgainstWall(true); end
		target:setTurnAlertedValues(-5, 5);	--- thank you Slayer!
	end
end

--- Creates a ask for seks context menu
-- @param ContextMenu object injected from ZomboWinContextMenu, can access ZomboWin functionalities with this
-- @param IsoPlayer object
-- @context Context menu object to be filled for
-- @worldobjects table of world objects nearby the player
return function(ContextMenu, playerObj, context, worldobjects)
	if not ZomboWinConfig.ModOptions.options.box1 then return; end

	local iIndex = 0
	local bNoPants = true;
	local player = playerObj:getPlayerNum();
	SexOption = {};
	SexSubMenu = {};
	
	if ZomboWinConfig.ModOptions.options.box4 and isWearingPants() then
		SexOption = context:addOption(getText("ContextMenu_Main"), worldobjects);	
		local tooltip = ISToolTip:new();
		tooltip:initialise();
		tooltip:setVisible(false);
		SexOption.notAvailable = true;
		description = " <RED>" .. getText("ContextMenu_Main_Pants");
		tooltip.description = description;
		SexOption.toolTip = tooltip;
		return;
	else
		--- Main Zombo Win option
		SexOption = context:addOption(getText("ContextMenu_Main"), worldobjects)	
		SexSubMenu = ISContextMenu:getNew(context)	
		context:addSubMenu(SexOption, SexSubMenu)	
	end
	
	--- Activate native fetch function to determine if our mouse selected a square containing an IsoPlayer
	ISWorldObjectContextMenu.clearFetch()
	for _, v in ipairs(worldobjects) do
		ISWorldObjectContextMenu.fetch(v, player, true)
	end
	
	---------------------------------- Asking for a friend ----------------------------------
	
	if ZomboWinConfig.ModOptions.options.box3 then
		--- Check if we have moused over a IsoPlayer
		if clickedPlayer then	-- only workes for others, not yourself.
			--print("isoplayer detected");
			local pp = getPlayer();
			if pp ~= clickedPlayer then ----- this will differentiate clicking self or clicking another player -----
				--print("non player iso detected");
				-- This will check other persons clothing.
				local iTheirClothes = clickedPlayer:getWornItems()
				if iTheirClothes then
				--- Loop through the character's currently equipped items for pants
					for i = iTheirClothes:size(), 1, -1 do
						local wornItem = iTheirClothes:get(i - 1) --- Get the current worn item

						if wornItem then
							local item = wornItem:getItem() --- Receive item data
							local location = wornItem:getLocation() --- Receive location of where this item is located on the body
							if item:IsClothing() then --- Make sure it is a clothing piece
								--- Iterate through the pants clothing list
								local isWearingPants = false
								
								for v = 1, #clothingHandler.checkPants do
									if bNoPants then
										local bodyPart = clothingHandler.checkPants[v]

										if location == bodyPart then
											bNoPants = false;
											isWearingPants = true;
										end
									end
								end
								
								if isWearingPants then
									break;
								end
							end
						end
					end
				end
			end
			
			--- enable bandit sex
			
			
			if bNoPants == true then			
				local sOption = SexSubMenu:addOption(getText("ContextMenu_AskForSex"), worldobjects)	
				local sSexSubMenu = ISContextMenu:getNew(context)	
				SexSubMenu:addSubMenu(sOption, sSexSubMenu)
				
				for iPosition = 1, #ListedPositions do	
					local text = getText(string.format("ContextMenu_AskForSex_%s", ListedPositions[iPosition]))
					if text then	
						--- Create the new sub option onAskForSex(worldobjects, contextMenu, position ,requestor, target)
						local animationOption = sSexSubMenu:addOption(text, worldobjects, onAskForSex, ContextMenu, iPosition, playerObj, clickedPlayer)
					else
						print(string.format("Missing Text: %s", anim))
					end
				end		
			else 
				local sOption = SexSubMenu:addOption(getText("ContextMenu_AskForSex"), worldobjects)		
				local tooltip = ISToolTip:new();
				tooltip:initialise();
				tooltip:setVisible(false);
				sOption.notAvailable = true;
				description = " <RED>" .. getText("ContextMenu_AskForSex_Pants");
				tooltip.description = description
				sOption.toolTip = tooltip
			end		
		end
	end
	
	---------------------------------- Mast ----------------------------------

	local isFemale = playerObj:isFemale()
	local animationList = {};
	if playerObj:isSitOnGround() then
		animationList = ContextMenu.Client.AnimationUtils:getAnimations(1, isFemale and 0 or 1, isFemale and 1 or 0, {"MastSit"})
	else
		animationList = ContextMenu.Client.AnimationUtils:getAnimations(1, isFemale and 0 or 1, isFemale and 1 or 0, {"Mast"})
	end
	--playerObj	
	local stats = playerObj:getStats()
	local bodyDamage = playerObj:getBodyDamage()
	local unhappiness = bodyDamage:getUnhappynessLevel()
	local stress = stats:getStress();
	local panic = stats:getPanic();
	local sickness = bodyDamage:getFoodSicknessLevel()
	--local groin = bodyDamage:getBodyPart(BodyPartType.FromString("Groin")) --- if Groin:getAdditionalPain() then ? end
	local pain = stats:getPain();
	
	--- true means pass, good to go!
	local anyDiscomfort = false;
	local innocentOutside = false;
	
	--- For tooltip conditions check
	local function checkForDiscomfort()
		--print("checkDiscomfort called.");
		if pain >= 10 then anyDiscomfort = true; end
		if unhappiness >= 46 then anyDiscomfort = true; end
		if panic >= 6 then anyDiscomfort = true; end
		if sickness >= 25 then anyDiscomfort = true; end
		if stress >= 25 then anyDiscomfort = true; end
		--print("Discomfort returned: " .. tostring(anyDiscomfort));
		return anyDiscomfort;
	end
	
	local function checkForInnocentImpedence()
		if playerObj:HasTrait("Innocent") and playerObj:isOutside() then innocentOutside = true; end
		return innocentOutside;
		--- editor note: use a check generic check possible bool first followed by these specific conditions!!
		--- currently innocent is not implemented.
	end
	
	--- For tooltip
	checkForDiscomfort();
	checkForInnocentImpedence();
	
	if anyDiscomfort or innocentOutside then
		local masturbateOption = SexSubMenu:addOption(getText("ContextMenu_Masturbate"), worldobjects)
		local tooltip = ISToolTip:new();
		tooltip:initialise();
		tooltip:setVisible(false);
		masturbateOption.notAvailable = true;
		if anyDiscomfort then 
			description = " <RED>" .. getText("ContextMenu_Mast_disc");
			tooltip.description = description;
			masturbateOption.toolTip = tooltip;
		end
		if innocentOutside then
			description = " <RED>" .. getText("ContextMenu_Mast_inno");
			tooltip.description = description;
			masturbateOption.toolTip = tooltip;
		end
	end
	
	--- For after all conditions met
	if not anyDiscomfort and not innocentOutside then
		--- Create an option in the right-click menu, and then creates a submenu for that
		local masturbateOption = SexSubMenu:addOption(getText("ContextMenu_Masturbate"), worldobjects)
		local masturbationSubMenu = ISContextMenu:getNew(context)
		SexSubMenu:addSubMenu(masturbateOption, masturbationSubMenu)
		--- Start creating our submenus based on the player's gender
		--[[for iPosition = 1, #mastPos do
			local text = getText(string.format("ContextMenu_%s", mastPos[iPosition]))
			if text then	
				--- Create the new sub option onAskForSex(worldobjects, contextMenu, position ,requestor, target)
				local animationOption = masturbationSubMenu:addOption(text, worldobjects, onAskForSex, ContextMenu, iPosition, playerObj, clickedPlayer)
			else
				print(string.format("Missing Text: %s", anim))
			end
		end]] ---working on random quick, regular, relaxed
		
		for i = 1, #animationList do
			local animation = animationList[i]
			local contextMenu_translate_text = string.format("ContextMenu_%s%s", animation.prefix, animation.id)
			local text = getText(contextMenu_translate_text)
			
			if text then
				--- Create a new tooltip when the player hovers over the sub option
				local toolTip = ISToolTip:new()
				toolTip.description = "" --- Make tooltip description in the future
				toolTip:setName(text)
				toolTip:initialise()
				toolTip:setVisible(false)

				--- Create the new sub option...emotional block here...before addoption w/ function
				local animationOption = {masturbationSubMenu:addOption(text, worldobjects, ContextMenu.Client.AnimationHandler.Play, {playerObj}, animation);}
				animationOption.toolTip = toolTip
			else
				print(string.format("Missing Text: %s", contextMenu_translate_text))
			end
		end
	end

	---------------------------------- Down Manip ----------------------------------
	
	local player = getPlayer();
	local enemies = player:getSpottedList()
	local maxDistance = 2

	for i = 0, enemies:size() - 1 do
		local enemy = enemies:get(i)
		if enemy:isZombie() and enemy:DistTo(player) <= maxDistance and enemy:isBeingSteppedOn() and not enemy:getModData().isSubdued then
			----- Check for Rope -----
			local weapon = player:getPrimaryHandItem()
			if weapon == nil then 
				local dOption = SexSubMenu:addOption(getText("ContextMenu_Subdue"), worldobjects);	
				local tooltip = ISToolTip:new();
				tooltip:initialise();
				tooltip:setVisible(false);
				dOption.notAvailable = true;
				description = " <RED>" .. getText("ContextMenu_Subdue_noRope");
				tooltip.description = description;
				dOption.toolTip = tooltip;
				break; 
			end
			if not weapon:hasTag("Rope") then 
				local dOption = SexSubMenu:addOption(getText("ContextMenu_Subdue"), worldobjects);	
				local tooltip = ISToolTip:new();
				tooltip:initialise();
				tooltip:setVisible(false);
				dOption.notAvailable = true;
				description = " <RED>" .. getText("ContextMenu_Subdue_noRope");
				tooltip.description = description;
				dOption.toolTip = tooltip;
			elseif weapon:hasTag("Rope") then
				local text = getText(string.format("ContextMenu_Subdue"))
				if text then	
					--- Create the new sub option onAskForSex(worldobjects, contextMenu, position ,requestor, target)
					local dOption = SexSubMenu:addOption(text, worldobjects, onSubdue, ContextMenu, iPosition, playerObj, enemy)
				else
					print(string.format("Missing Text: %s", anim))
				end
			end
		elseif enemy:isZombie() and enemy:DistTo(player) <= maxDistance and enemy:getModData().isSubdued then
			if not isPanickedCheck() then
				local dSexSubMenu = ISContextMenu:getNew(context);
				--- Release menu option
				local text = getText(string.format("ContextMenu_Release"))
				if text then	
					--- Create the new sub option onAskForSex(worldobjects, contextMenu, position ,requestor, target)
					local dOption = SexSubMenu:addOption(text, worldobjects, onRelease, ContextMenu, iPosition, playerObj, enemy)
				else
					print(string.format("Missing Text: %s", anim))
				end
				--- end
				if enemy:isUseless() and enemy:getModData().isSubdued and zwEXP then
					if not player:HasTrait("Innocent") then
						local dOption = SexSubMenu:addOption(getText("ContextMenu_DefeatForSex"), worldobjects)	
						SexSubMenu:addSubMenu(dOption, dSexSubMenu);
						for iPosition = 1, #ListedPositions do	
							local text = getText(string.format("ContextMenu_DefeatForSex_%s", ListedPositions[iPosition]))
							if text then	
								--- Create the new sub option onAskForSex(worldobjects, contextMenu, position ,requestor, target)
								local animationOption = dSexSubMenu:addOption(text, worldobjects, onDefeatForSex, ContextMenu, iPosition, playerObj, enemy)
							else
								print(string.format("Missing Text: %s", anim))
							end
						end	
					else
						local dOption = SexSubMenu:addOption(getText("ContextMenu_DefeatForSex"), worldobjects);	
						local tooltip = ISToolTip:new();
						tooltip:initialise();
						tooltip:setVisible(false);
						dOption.notAvailable = true;
						description = " <RED>" .. getText("ContextMenu_DefeatForSex_Inno");
						tooltip.description = description;
						dOption.toolTip = tooltip;
						break; 
					end
				end
			elseif isPanickedCheck() and zwEXP then
				dOption = SexSubMenu:addOption(getText("ContextMenu_DefeatForSex"), worldobjects);	
				local tooltip = ISToolTip:new();
				tooltip:initialise();
				tooltip:setVisible(false);
				dOption.notAvailable = true;
				description = " <RED>" .. getText("ContextMenu_DefeatForSex_Panic");
				tooltip.description = description;
				dOption.toolTip = tooltip;
				break;
			elseif not zwEXP then
				dOption = SexSubMenu:addOption(getText("ContextMenu_NeedzwEXP"), worldobjects);	
				local tooltip = ISToolTip:new();
				tooltip:initialise();
				tooltip:setVisible(false);
				dOption.notAvailable = true;
				description = " <RED>" .. getText("ContextMenu_NeedzwEXP2");
				tooltip.description = description;
				dOption.toolTip = tooltip;
				break;
			end
		elseif enemy:isZombie() and enemy:DistTo(player) <= maxDistance and enemy:getVariableBoolean("Bandit") and not Bandit.IsHostile(enemy) and not enemy:getModData().isSubdued and zwEXP then
			if not isPanickedCheck() then
				local sOption = SexSubMenu:addOption(getText("ContextMenu_AskForSex"), worldobjects)	
				local sSexSubMenu = ISContextMenu:getNew(context);
				SexSubMenu:addSubMenu(sOption, sSexSubMenu);
				
				for iPosition = 1, #ListedPositions do	
					local text = getText(string.format("ContextMenu_AskForSex_%s", ListedPositions[iPosition]))
					if text then	
						--- Create the new sub option onAskForSex(worldobjects, contextMenu, position ,requestor, target)
						local animationOption = sSexSubMenu:addOption(text, worldobjects, onDefeatForSex, ContextMenu, iPosition, playerObj, enemy)
					else
						print(string.format("Missing Text: %s", anim))
					end
				end	
			elseif isPanickedCheck() then
				dOption = SexSubMenu:addOption(getText("ContextMenu_DefeatForSex"), worldobjects);	
				local tooltip = ISToolTip:new();
				tooltip:initialise();
				tooltip:setVisible(false);
				dOption.notAvailable = true;
				description = " <RED>" .. getText("ContextMenu_DefeatForSex_Panic");
				tooltip.description = description;
				dOption.toolTip = tooltip;
				break;
			end
		end
	end

	---------------------------------- Down Subdue ----------------------------------

end
