require "TimedActions/ISBaseTimedAction"
pcall(require, "ZomboWin/ZomboWinAnimationUtils")
pcall(require, "ZomboWin/ZomboWinAnimationHandler")

Kinkocalypse = Kinkocalypse or {}
local ISBaseTimedAction = ISBaseTimedAction
local ISTimedActionQueue = ISTimedActionQueue

-- compability with excrtementum
Kinkocalypse.ExcrementumDefecateDropPantsActionStart = nil
Kinkocalypse.ExcrementumUrinateDropPantsActionStart = nil

-- make compability with ZomboWin
Kinkocalypse.ZomboWinAnimationUtils_PlayAnimationOrig = nil
Kinkocalypse.ZomboWinISAnimationActionOrigStart = nil
Kinkocalypse.MasturbationActions = 
{
	"blabla_F_Standing_Relaxed_Fingering_01", 
	"blabla_F_Standing_Regular_Fingering_02",
	"blabla_F_Standing_Regular_Fingering_01",
	"blabla_F_Standing_Quick_Fingering_02",
	"blabla_F_Standing_Quick_Fingering_01", 
	"blabla_F_Sitting_Relaxed_Fingering_01",
	"blabla_F_Sitting_Regular_Fingering_01",
	"blabla_F_Sitting_Quick_Fingering_02",
	"blabla_F_Sitting_Quick_Fingering_01",
	"Yonchi_titstease", 
	"Yonchi_doggyfingeringintense",
	"Yonchi_doggyfingering",
	"nominal_SittingRelaxedWank",
	"nominal_SittingRegularWank",
	"nominal_RelaxedWank", 
	"nominal_RegularWank",
	"nominal_QuickWank",
	"nominal_F_SittingRelaxedFingering",
	"nominal_F_SittingRegularFingering",
	"nominal_F_RelaxedFingering", 
	"nominal_F_RegularFingering",
	"nominal_F_QuickFingering"
}
Kinkocalypse.TitsMasturbationActions = { "Yonchi_titstease" }
Kinkocalypse.AnusMasturbationActions = { }

Kinkocalypse.CheckTag = function(tbl, tag)
	for _, value in ipairs(tbl) do
        if value == tag then return true end
    end
    return false
end

Kinkocalypse.ISAnimationActionStart = function(self)
	local canStart = true
	local equipedTags = Kinkocalypse.GetPlayerEquipedRestrictionsTags()
	local isMasturbation = Kinkocalypse.CheckTag(Kinkocalypse.MasturbationActions, self.animation)
	local isTitsMasturbation = Kinkocalypse.CheckTag(Kinkocalypse.TitsMasturbationActions, self.animation)
	local isAnusMasturbation = false
	local isMasturbationAny = isMasturbation or isTitsMasturbation or isAnusMasturbation
	
	if Kinkocalypse.ControllCenterIsOn() == true and Kinkocalypse.IsPunishmentActive("NoMasturbate") == true and isMasturbationAny then
		Kinkocalypse.AddPunishmentScore(ZombRand(20, 50), getText("UI_Kincalypse_ViolateMaturbateRule"))
		Kinkocalypse.AddPunishment("NoMasturbate", 120 + ZombRand(180))
		local addExtraPunishment = false
		local extraPunishDuration = 60 + ZombRand(120)
		local silent = true
		if ZombRand(100) > 80 then
			if isMasturbation or isAnusMasturbation then Kinkocalypse.AddPunishment("GenitalClamp", extraPunishDuration, silent)
			else Kinkocalypse.AddPunishment("NippleClamps", extraPunishDuration, silent) end
			addExtraPunishment = true end
		if ZombRand(100) > 50 then Kinkocalypse.AddPunishment("HandsBack", extraPunishDuration, silent); addExtraPunishment = true end
		if ZombRand(100) > 20 then Kinkocalypse.AddPunishment("Aphrodisiac", extraPunishDuration, silent); addExtraPunishment = true end
		if addExtraPunishment then Kinkocalypse.Say(getText("UI_Kincalypse_Controller_BadSlave")) end
		canStart = false
	end
	
	if equipedTags["ChainedHandsBack"] ~= nil and (isMasturbation or isTitsMasturbation) then
		Kinkocalypse.Say(getText("UI_Kincalypse_HandsCuffedCantDo2"))
		canStart = false
	elseif equipedTags["SteelChastityBelt"] ~= nil and isMasturbation then 
		Kinkocalypse.Say(getText("UI_Kincalypse_DamnBelt"))
		canStart = false
	elseif equipedTags["SteelChastityBra"] ~= nil and isTitsMasturbation then 
		Kinkocalypse.Say(getText("UI_Kincalypse_DamnBra"))
		canStart = false
	elseif equipedTags["SteelAnalPlug"] ~= nil and isAnusMasturbation then 
		Kinkocalypse.Say(getText("UI_Kincalypse_DamnPlug"))
		canStart = false
	end

	if canStart ~= true then
		ISAnimationAction.stop(self)
		return
	end

	return Kinkocalypse.ZomboWinISAnimationActionOrigStart(self)
end

-----------------------------------------------------------------------

ISKinkAnimationAction = ISBaseTimedAction:derive("ISKinkAnimationAction")

function Kinkocalypse.PlayAction(player, equipedTags, actionData)
	if actionData == nil then return end
	if actionData.requiredArousal == nil or actionData.requiredArousal < 0 then 
		actionData.requiredArousal = 35 + ZombRand(15) 
	end
	
	local ArousalLevel = player:getModData().Arousal 
	if ArousalLevel < actionData.requiredArousal then
		Kinkocalypse.Say(getText("UI_Kincalypse_NotHorny"))
		return
	end

	local x, y, z = player:getX(), player:getY(), player:getZ()
	local action = ISKinkAnimationAction:new(player, actionData.animation, actionData.duration)
	action.equipedTags = equipedTags
	action.actionData = actionData
	action.position = {x = x, y = y, z = z}

	if actionData.canStop ~= true then
		action.stopOnWalk = false
		action.stopOnRun = false
		action.stopOnAim = false
	end
	
	if actionData.canMove ~= true then
		ISTimedActionQueue.clear(player)
	end		
	ISTimedActionQueue.add(action)
end

--- Make sure to keep the TimedAction running
function ISKinkAnimationAction:isValid() return true end

--- Runs every frame during the animations
function ISKinkAnimationAction:update()
	if self.position and self.actionData.canMove ~= true then
		self.character:setX(self.position.x)
		self.character:setY(self.position.y)
		self.character:setZ(self.position.z)
	end

	if not self.character:getCharacterActions():contains(self.action) then
		self:forceStop()
	end
end

--- Timed action completes
function ISKinkAnimationAction:perform()
	local ArousalLevel = self.character:getModData().Arousal
	local canFinish = true

	if Kinkocalypse.ControllCenterIsOn() == true and Kinkocalypse.IsPunishmentActive("NoMasturbate") == true then
		Kinkocalypse.AddPunishmentScore(ZombRand(20, 50), getText("UI_Kincalypse_ViolateMaturbateRule"))
		Kinkocalypse.AddPunishment("NoMasturbate", 120 + ZombRand(180))
		if ZombRand(100) > 50 then Kinkocalypse.AddPunishment("HandsBack", 60 + ZombRand(120)) end
	end
	
	if self.equipedTags["ChainedHandsBack"] ~= nil and self.actionData.id ~= "Masturbate_Anus" then
		Kinkocalypse.Say(getText("UI_Kincalypse_HandsCuffedCantDo2"))
		canFinish = false
	elseif self.equipedTags["SteelChastityBelt"] ~= nil and self.actionData.id == "Masturbate_Genetails" then 
		Kinkocalypse.Say(getText("UI_Kincalypse_DamnBelt"))
		canFinish = false
	elseif self.equipedTags["SteelChastityBra"] ~= nil and self.actionData.id == "Masturbate_Tits" then 
		Kinkocalypse.Say(getText("UI_Kincalypse_DamnBra"))
		canFinish = false
	elseif self.equipedTags["SteelAnalPlug"] ~= nil and self.actionData.id == "Masturbate_Anus" then 
		Kinkocalypse.Say(getText("UI_Kincalypse_DamnPlug"))
		canFinish = false
	end
	
	if canFinish == true then
		Kinkocalypse.DoOrgasm(self.character, self.equipedTags, ZombRand(self.actionData.arousalReduceMin or 25, self.actionData.arousalReduceMax or 50))
	else
		self.character:getModData().Arousal = ArousalLevel + (self.actionData.arousalOnFail or ZombRand(5, 15))
	end
	Kinkocalypse.Say(getText("UI_Kincalypse_Arosal")..string.format("%.2f", self.character:getModData().Arousal).."]")
	ISBaseTimedAction.perform(self)
end

function ISKinkAnimationAction:stop()
	if self.actionData.canStop == true then
		ISBaseTimedAction.stop(self)
	end
end

function ISKinkAnimationAction:start()
	self.maxTime = self.duration
	self.action:setTime(self.maxTime)
	self:setActionAnim(self.animation)
	if self.equipedTags["ChainedHandsBack"] == nil then
		self:setOverrideHandModels(nil, nil)
	end
end

function ISKinkAnimationAction:new(character, animation, duration)
	local object = 
	{
		character = character,
		animation = animation,
		stopOnWalk = true,
		stopOnRun = true,
		ignoreHandsWounds = true,
		maxTime = -1, --- Gets set in start()
		duration = duration or 60,
		ended = false,
	}
	setmetatable(object, self)
	self.__index = self
	return object
end
