-- parasite_utils.lua
-- Shared utilities for staged parasite progression.
-- dofile_once() this from any parasite script.

-----------------------------------------------------------------------------------------
-- STAGE READ / WRITE
-----------------------------------------------------------------------------------------
--- Returns stage, stage_start_frame, vsc_component for a parasite entity.
--- Falls back to stage 1 if no stage VSC exists (legacy parasites).
function get_parasite_stage(parasite_entity)
	for _, comp in ipairs(EntityGetComponent(parasite_entity, "VariableStorageComponent") or {}) do
		if ComponentGetValue2(comp, "name") == "parasite_stage" then
			return tonumber(ComponentGetValue2(comp, "value_int")) or 1,
			       tonumber(ComponentGetValue2(comp, "value_string")) or 0,
			       comp
		end
	end
	return 1, 0, nil
end

--- Sets the stage on a parasite entity and resets the stage timer.
function set_parasite_stage(parasite_entity, new_stage)
	for _, comp in ipairs(EntityGetComponent(parasite_entity, "VariableStorageComponent") or {}) do
		if ComponentGetValue2(comp, "name") == "parasite_stage" then
			ComponentSetValue2(comp, "value_int", new_stage)
			ComponentSetValue2(comp, "value_string", tostring(GameGetFrameNum()))
			return
		end
	end
end

-----------------------------------------------------------------------------------------
-- TIME-BASED AUTO-ADVANCEMENT
-----------------------------------------------------------------------------------------
-- How long (in frames) a parasite must sit at a given stage before auto-advancing.
-- Ramps up: early stages advance faster, later stages take much longer.
local STAGE_TIME_THRESHOLDS = {
	[1] =  180 * 60,   -- 3 min  →  stage 2
	[2] =  360 * 60,   -- 6 min  →  stage 3
	[3] =  600 * 60,   -- 10 min →  stage 4
	[4] =  900 * 60,   -- 15 min →  stage 5
}

--- Checks whether enough time has elapsed to auto-advance the parasite.
--- Returns current_stage, did_advance (boolean).
--- If it advanced, the VSC is already updated.
function check_parasite_time_advance(parasite_entity, max_stage)
	local stage, stage_start, vsc = get_parasite_stage(parasite_entity)
	if vsc == nil or stage >= max_stage then return stage, false end

	local elapsed  = GameGetFrameNum() - stage_start
	local threshold = STAGE_TIME_THRESHOLDS[stage] or (600 * 60)

	if elapsed >= threshold then
		local new_stage = stage + 1
		ComponentSetValue2(vsc, "value_int", new_stage)
		ComponentSetValue2(vsc, "value_string", tostring(GameGetFrameNum()))
		return new_stage, true
	end

	return stage, false
end

-----------------------------------------------------------------------------------------
-- SPAWN INTERVAL SCALING
-----------------------------------------------------------------------------------------
--- Returns a multiplier (0.0–1.0) that shrinks spawn intervals as stage rises.
---   stage 1 → 1.00 (normal)
---   stage 2 → 0.75
---   stage 3 → 0.55
---   stage 4 → 0.40
---   stage 5 → 0.30
function get_spawn_interval_mult(stage)
	local mults = { [1]=1.00, [2]=0.75, [3]=0.55, [4]=0.40, [5]=0.30 }
	return mults[stage] or 1.00
end

-----------------------------------------------------------------------------------------
-- STAGE LABEL FOR UI
-----------------------------------------------------------------------------------------
local STAGE_LABELS = { "I", "II", "III", "IV", "V" }
function get_stage_label(stage)
	return STAGE_LABELS[stage] or tostring(stage)
end

-----------------------------------------------------------------------------------------
-- UNIFIED STAGE CHANGE DETECTION
-- Catches BOTH time-based auto-advance AND sex-triggered instant advance.
-- Call once per tick; returns current_stage, true if stage changed this tick.
-----------------------------------------------------------------------------------------
function check_parasite_stage_change(parasite_entity, max_stage, global_key)
	-- First try time-based advancement
	local stage, time_advanced = check_parasite_time_advance(parasite_entity, max_stage)

	-- Check if stage differs from last announced (catches sex-triggered advances)
	local last_announced = tonumber(GlobalsGetValue(global_key, "1")) or 1
	if stage > last_announced then
		GlobalsSetValue(global_key, tostring(stage))
		return stage, true
	end

	return stage, false
end

-----------------------------------------------------------------------------------------
-- OVERLAY VISUAL SYSTEM
-- Adds a SpriteComponent overlay to the player matching the player_dress pattern.
-- Each parasite type has per-stage spritesheets in data/enemies_gfx/parasite_overlays/.
-- Overlays appear only during the final two stages per parasite.
-----------------------------------------------------------------------------------------
dofile_once("mods/lewd_noita/files/status_effects/parasite_overlay.lua")

function update_parasite_overlay(player_id, overlay_name, stage, overlay_table)
	update_parasite_visual(player_id, overlay_name, stage)
end

function remove_parasite_overlay(player_id, overlay_name)
	remove_parasite_visual(player_id, overlay_name)
end

-----------------------------------------------------------------------------------------
-- PARTICLE EMITTER SYSTEM
-- Attaches/removes persistent particle emitter entities on the player.
-----------------------------------------------------------------------------------------
function attach_parasite_emitter(player_id, emitter_name, emitter_xml)
	for _, child in ipairs(EntityGetAllChildren(player_id) or {}) do
		if EntityGetName(child) == emitter_name then return end
	end
	local e = EntityLoad(emitter_xml)
	if e and e ~= 0 then
		EntitySetName(e, emitter_name)
		EntityAddComponent2(e, "InheritTransformComponent", {})
		EntityAddChild(player_id, e)
	end
end

function remove_parasite_emitter(player_id, emitter_name)
	for _, child in ipairs(EntityGetAllChildren(player_id) or {}) do
		if EntityGetName(child) == emitter_name then
			EntityKill(child)
			return
		end
	end
end

-----------------------------------------------------------------------------------------
-- NAMED VSC LOOKUP
-- EntityGetFirstComponent returns arbitrary VSC when multiple exist.
-- Always use this to get the spawn timer VSC by name.
-----------------------------------------------------------------------------------------
function get_parasite_timer_vsc(parasite_entity)
	for _, comp in ipairs(EntityGetComponent(parasite_entity, "VariableStorageComponent") or {}) do
		if ComponentGetValue2(comp, "name") == "parasite_timer" then
			return comp
		end
	end
	return nil
end
