-- parasite_overlay.lua
-- Multiple parasite overlays can be active simultaneously. Priority (low->high,
-- high overrides/draws over low): fly, firebug, mushroom, hornygasflower, spider, ant, rat.
-- longleg reuses the spider sprites and shares spider's priority slot.
-- (loaded by parasite_utils.lua, do not re-dofile_once to avoid circular dependency)

local TAG_PREFIX = "ln_overlay_"

local PARASITE_MAX_STAGE = {
	fly            = 5,
	firebug        = 5,
	fungus         = 4,
	hornygasflower = 4,
	spider         = 5,
	longleg        = 5,
	ant            = 5,
	rat            = 5,
}

-- Lower number = lower priority (drawn first / overridden by later ones).
local PRIORITY = {
	fly            = 1,
	firebug        = 2,
	fungus         = 3,
	hornygasflower = 4,
	spider         = 5,
	longleg        = 5, -- shares spider's slot/art
	ant            = 6,
	rat            = 7,
}

-- Sprite asset name used on disk (longleg reuses spider art).
local ASSET_NAME = {
	longleg = "spider",
}

local function asset_for(parasite_type)
	return ASSET_NAME[parasite_type] or parasite_type
end

local function z_for(parasite_type)
	-- Dress sits at 0.5; player body ~0.6. Draw overlays above dress, stacked by priority.
	local p = PRIORITY[parasite_type] or 0
	return 0.56 + (p * 0.005)
end

local function overlay_xml_candidates(asset, stage)
	local file = asset .. "_stage" .. stage .. ".xml"
	return {
		"data/enemies_gfx/parasite_overlays/" .. file,
		"mods/lewd_noita/data/enemies_gfx/parasite_overlays/" .. file,
	}
end

local function resolve_overlay_xml(asset, stage)
	for _, path in ipairs(overlay_xml_candidates(asset, stage)) do
		local content = ModTextFileGetContent(path)
		if content ~= nil and content ~= "" then
			return path
		end
	end
	return nil
end

local function find_overlay_sprite(player_id, parasite_type)
	local tag = TAG_PREFIX .. parasite_type
	for _, comp in ipairs(EntityGetComponent(player_id, "SpriteComponent") or {}) do
		if ComponentHasTag(comp, tag) then
			return comp
		end
		local tags = ComponentGetValue2(comp, "_tags") or ""
		if tags:find(tag, 1, true) then
			return comp
		end
	end
	return nil
end

local function get_player_body_sprite(player_id)
	for _, comp in ipairs(EntityGetComponent(player_id, "SpriteComponent") or {}) do
		if not ComponentHasTag(comp, "ln_dress") then
			local tags = ComponentGetValue2(comp, "_tags") or ""
			if not tags:find("ln_overlay_", 1, true) then
				local image_file = ComponentGetValue2(comp, "image_file") or ""
				if not image_file:find("player_dress", 1, true) then
					return comp
				end
			end
		end
	end
	return EntityGetFirstComponent(player_id, "SpriteComponent")
end

local function sync_overlay_animation(player_id, overlay_comp)
	if overlay_comp == nil then return end
	local body = get_player_body_sprite(player_id)
	if body == nil then return end

	local anim = ComponentGetValue2(body, "rect_animation") or ""
	if anim ~= "" then
		local cur = ComponentGetValue2(overlay_comp, "rect_animation") or ""
		if cur ~= anim then
			ComponentSetValue2(overlay_comp, "rect_animation", anim)
		end
	end
end

--- Apply or update the visual overlay for a parasite at the given stage.
--- Overlays only appear during the final two stages of each parasite.
function update_parasite_visual(player_id, parasite_type, stage)
	if player_id == nil or player_id == 0 then return end
	stage = stage or 1

	local max_stage = PARASITE_MAX_STAGE[parasite_type] or 5
	if stage < max_stage - 1 then
		remove_parasite_visual(player_id, parasite_type)
		return
	end

	local asset = asset_for(parasite_type)
	local xml_path = resolve_overlay_xml(asset, stage)
	if xml_path == nil then
		remove_parasite_visual(player_id, parasite_type)
		return
	end

	local existing = find_overlay_sprite(player_id, parasite_type)
	local tag = TAG_PREFIX .. parasite_type

	if existing then
		local cur_file = ComponentGetValue2(existing, "image_file") or ""
		if cur_file ~= xml_path then
			ComponentSetValue2(existing, "image_file", xml_path)
			EntityRefreshSprite(player_id, existing)
		end
	else
		existing = EntityAddComponent2(player_id, "SpriteComponent", {
			_tags      = "character," .. tag,
			image_file = xml_path,
			offset_x   = 10,
			offset_y   = 17,
			z_index    = z_for(parasite_type),
			visible    = true,
		})
		if existing ~= nil then
			EntityRefreshSprite(player_id, existing)
		end
	end

	if existing ~= nil then
		ComponentSetValue2(existing, "visible", true)
		EntitySetComponentIsEnabled(player_id, existing, true)
		sync_overlay_animation(player_id, existing)
	end

	GlobalsSetValue("LN_OVERLAY_STAGE_" .. parasite_type, tostring(stage))
end

--- Remove the visual overlay for a parasite (call on cure/removal).
function remove_parasite_visual(player_id, parasite_type)
	if player_id == nil or player_id == 0 then return end

	local existing = find_overlay_sprite(player_id, parasite_type)
	if existing then
		EntityRemoveComponent(player_id, existing)
	end
	GlobalsSetValue("LN_OVERLAY_STAGE_" .. parasite_type, "0")
end

function has_parasite_visual(player_id, parasite_type)
	return find_overlay_sprite(player_id, parasite_type) ~= nil
end

function remove_all_parasite_visuals(player_id)
	if player_id == nil or player_id == 0 then return end
	for ptype, _ in pairs(PRIORITY) do
		remove_parasite_visual(player_id, ptype)
	end
end

function refresh_parasite_overlays(player_id)
	if player_id == nil or player_id == 0 then return end
	for ptype, _ in pairs(PRIORITY) do
		local comp = find_overlay_sprite(player_id, ptype)
		if comp ~= nil then
			sync_overlay_animation(player_id, comp)
		end
	end
end
