-- @author DoomTero 2026
-- @copyright 2026 DoomTero - ZomboRut original work. ref:dd38acff
-- @license Proprietary. Not licensed for reuse, redistribution or derivative works without written permission from DoomTero. Ask - permission is obtainable. See ZomboRut/LICENSE.txt

require('NPCs/MainCreationMethods')

local getText = getText
local string = string

local MODULE = "zomborut"

local VANILLA_ALIASES = {
    Conspicuous = "base:conspicuous",
    Inconspicuous = "base:inconspicuous",
    Desensitized = "base:desensitized",
    Brave = "base:brave",
    Cowardly = "base:cowardly",
}
local function resolveTrait(name)
    local loc = VANILLA_ALIASES[name] or (MODULE .. ":" .. name:lower())
    return CharacterTrait.get(ResourceLocation.of(loc))
end

local function pairExclusive(aName, bName)
    local a, b = resolveTrait(aName), resolveTrait(bName)
    local defA = a and CharacterTraitDefinition.getCharacterTraitDefinition(a)
    local defB = b and CharacterTraitDefinition.getCharacterTraitDefinition(b)
    if not defA or not defB then
        local missing = (not defA) and aName or bName
        if not defA and not defB then missing = aName .. " + " .. bName end
        DebugLog.log("[ZR traits] skipped exclusive " .. aName .. " <-> " .. bName
            .. " - no CharacterTraitDefinition for " .. missing)
        return
    end
    CharacterTraitDefinition.setMutualExclusive(a, b)
end

local TRAITS_LIST = {
	{
		IdentifierType = "Sexaddict",
		Cost = -4,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "Masochist",
		Cost = 2,
		Profession = false,
		MutualExclusives = {},
		Callback = function(trait)
			trait:addXPBoost(Perks.Lightfoot, 1)
		end
	},
	{
		IdentifierType = "Rapist",
		Cost = 4,
		Profession = false,
		MutualExclusives = {},
		Callback = function(trait)
			trait:addXPBoost(Perks.Sneak, 1)
			trait:addXPBoost(Perks.LongBlade, 1)
		end
	},
	{
		IdentifierType = "Wimp",
		Cost = -4,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "Necrophiliac",
		Cost = 3,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "Virgin",
		Cost = 3,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "Inexperienced",
		Cost = 3,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "Experienced",
		Cost = 3,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "Nymphomaniac",
		Cost = 6,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "Innocent",
		Cost = -5,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "Lewd",
		Cost = 4,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "Traumatized",
		Cost = 0,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "succubus",
		Cost = 5,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "submissive",
		Cost = -3,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "dominate",
		Cost = 5,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "youngBuck",
		Cost = 3,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "AARP",
		Cost = -2,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "inPrime",
		Cost = 2,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "spunkDefault",
		Cost = 0,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "lowEffort",
		Cost = 3,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "smokesAfter",
		Cost = 2,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "betterAlive",
		Cost = 4,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "itFollows",
		Cost = -8,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "promiscuous",
		Cost = 0,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "swinger",
		Cost = 2,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "unkempt",
		Cost = -5,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "neatTidy",
		Cost = 2,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "lovesClean",
		Cost = 5,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "viciousZombies",
		Cost = -5,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "dpress",
		Cost = 0,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "proteinDiet",
		Cost = 3,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "hydration",
		Cost = 2,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "drained",
		Cost = -2,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "fighter",
		Cost = 4,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "glassBones",
		Cost = -9,
		Profession = false,
		MutualExclusives = {},
	},
	{
		IdentifierType = "cardioJunkie",
		Cost = 5,
		Profession = false,
		MutualExclusives = {},
	},
}

local function _initTraits()
	for i = 1, #TRAITS_LIST do
		local data = TRAITS_LIST[i]
		local id   = data.IdentifierType
		local loc  = MODULE .. ":" .. id:lower()
		local nameKey = string.format("UI_ZL_Trait_%s", id)
		local descKey = string.format("UI_ZL_Trait_%s_Description", id)

		local trait = CharacterTrait.register(loc)
		local def   = CharacterTraitDefinition.addCharacterTraitDefinition(
			trait, nameKey, data.Cost, descKey, data.Profession
		)

		if data.Callback then
			data.Callback(def)
		end

		for v = 1, #data.MutualExclusives do
			pairExclusive(id, data.MutualExclusives[v])
		end
	end

	local X = pairExclusive

	X("Virgin", "Inexperienced")
	X("Virgin", "Experienced")
	X("Virgin", "Nymphomaniac")
	X("Inexperienced", "Experienced")
	X("Inexperienced", "Nymphomaniac")
	X("Experienced", "Nymphomaniac")
	X("Innocent", "Lewd")
	X("Innocent", "Nymphomaniac")
	X("Innocent", "Sexaddict")
	X("Innocent", "succubus")
	X("Innocent", "Rapist")
	X("Sexaddict", "Virgin")
	X("hydration", "drained")
	X("Wimp", "Rapist")
	X("Wimp", "Masochist")
	X("Wimp", "Nymphomaniac")
	X("Wimp", "Lewd")
	X("dominate", "submissive")
	X("dominate", "Wimp")
	X("youngBuck", "AARP")
	X("youngBuck", "inPrime")
	X("AARP", "inPrime")
	X("AARP", "lowEffort")
	X("lowEffort", "youngBuck")
	X("lowEffort", "inPrime")
	X("itFollows", "succubus")
	X("promiscuous", "Innocent")
	X("promiscuous", "swinger")
	X("swinger", "Innocent")
	X("unkempt", "neatTidy")
	X("unkempt", "lovesClean")
	X("neatTidy", "lovesClean")
end

local initTraits2 = function()
	local conspicuous2 = CharacterTrait.register(MODULE .. ":conspicuous2")
	CharacterTraitDefinition.addCharacterTraitDefinition(
		conspicuous2,
		"UI_trait_Conspicuous", 0,
		"UI_trait_ConspicuousDesc",
		true
	)

	local desensitized2 = CharacterTrait.register(MODULE .. ":desensitized2")
	CharacterTraitDefinition.addCharacterTraitDefinition(
		desensitized2,
		"UI_trait_Desensitized", 0,
		"UI_trait_DesensitizedDesc",
		true
	)

	local X = pairExclusive
	X("Conspicuous2", "Conspicuous")
	X("Conspicuous2", "Inconspicuous")
	X("Desensitized2", "Desensitized")
	X("Desensitized2", "Brave")
	X("Desensitized2", "Cowardly")
end

local function prostituteOccupation()
	local prof = CharacterProfession.register(MODULE .. ":prostitute")
	local def  = CharacterProfessionDefinition.addCharacterProfessionDefinition(
		prof,
		"UI_prof_prostitute",
		2,
		"UI_profdesc_prostitute",
		"prof_Prostitute"
	)
	def:addXPBoost(Perks.Aiming, 1)
	def:addGrantedTrait(resolveTrait("promiscuous"))
	def:addGrantedTrait(resolveTrait("Conspicuous2"))
end

local function sexSlaveOccupation()
	local prof = CharacterProfession.register(MODULE .. ":sexslave")
	local def  = CharacterProfessionDefinition.addCharacterProfessionDefinition(
		prof,
		"UI_prof_sexslave",
		-3,
		"UI_profdesc_sexslave",
		"prof_sexslave"
	)
	def:addXPBoost(Perks.Strength, -2)
	def:addXPBoost(Perks.Fitness, -2)
	def:addGrantedTrait(resolveTrait("Desensitized2"))
	def:addGrantedTrait(resolveTrait("dpress"))
end

local pTraitsInit = function(playernum, character)
	local player = getSpecificPlayer(playernum);
	local pTraits = player:getCharacterTraits();

	if ZR_Trait.has(player, "Conspicuous2") then
		pTraits:remove(ZR_Trait.Conspicuous2);
		pTraits:add(ZR_Trait.Conspicuous);
	end

	if ZR_Trait.has(player, "Desensitized2") then
		pTraits:remove(ZR_Trait.Desensitized2);
		pTraits:add(ZR_Trait.Desensitized);
	end

	if not ZR_Trait.has(player, "spunkDefault") and not ZR_Trait.has(player, "AARP") and not ZR_Trait.has(player, "inPrime") and not ZR_Trait.has(player, "youngBuck") and not ZR_Trait.has(player, "lowEffort") then
		pTraits:add(ZR_Trait.spunkDefault);
	end

end

local function pStartGear(player)
	local desc = player:getDescriptor();
	local currentProf = desc and desc:getCharacterProfession() or nil;
	local prostituteProf  = CharacterProfession.get(ResourceLocation.of("zomborut:prostitute"));

	if currentProf ~= nil and currentProf == prostituteProf then
		player:getInventory():AddItem("Base.Revolver", 1);
		player:getInventory():AddItem("Base.Bullets357", 1);
		player:getInventory():AddItem("Base.Bullets357", 1);
		player:getInventory():AddItem("Base.Bullets357", 1);
		player:getInventory():AddItem("Base.Bullets357", 1);
		player:getInventory():AddItem("Base.Bullets357", 1);
		player:getInventory():AddItem("Base.Bullets357", 1);
	end

	if ZR_Trait.has(player, "Rapist") then
		player:getInventory():AddItem("Base.KitchenKnife", 1);
		player:getInventory():AddItem("Base.Rope", 1);
		player:getInventory():AddItem("Base.DuctTape", 1);
	end
end

Events.OnGameBoot.Add(_initTraits);
Events.OnGameBoot.Add(initTraits2);
Events.OnGameBoot.Add(prostituteOccupation);
Events.OnGameBoot.Add(sexSlaveOccupation);

Events.OnCreatePlayer.Add(pTraitsInit)
Events.OnNewGame.Add(pStartGear)