-- luacheck: globals MyModGlobal Character Hook EnsurePatch CLIENT
if not CLIENT then return end
local utils = require "Cyka.utils"
local dump = require "Cyka.dump"

-- TODO: Also cook terminal
-- terminal d:28 t:logic,smallitem c:Terminal, Holdable, ConnectionPanel,
local machines = "fabricator,deconstructor,medicalfabricator"
Hook.Patch("Cyka", "Barotrauma.Character", "CanInteractWith",
	{ "Barotrauma.Item", "System.Single&", "System.Boolean" },
	function(_, ptable)
		local item = ptable["item"]
		if machines:find(tostring(item.Prefab.Identifier.Value)) then
			ptable.ReturnValue = true
		end
	end,
	Hook.HookMethodType.After
)

local cachedFabricator = nil
local cachedDeconstructor = nil
local cachedMedicalFabricator = nil

local function select(item)
	MyModGlobal.debugPrint("Selecting " .. tostring(item))
	item.Prefab.GrabWhenSelected = false
	Character.Controlled.SelectedItem = item
end

---@param prefabIdentifier string
---@param componentName string
---@return Barotrauma.Item, Barotrauma.Items.Components
local function findByComponent(prefabIdentifier, componentName)
	local items = utils.enqueueAllSubmarineItems({}, function(item)
		return item.Prefab.Identifier.Value == prefabIdentifier, item.Prefab.Identifier.Value == prefabIdentifier
	end)
	if #items == 0 then
		MyModGlobal.debugPrint("No " .. componentName .. " found")
		return nil, nil
	end
	if #items > 1 then
		MyModGlobal.debugPrint("Multiple " .. componentName .. " found, using first one")
		return nil, nil
	end

	---@type Barotrauma.Item
	local item = items[1]
	---@type Barotrauma.Items.Components
	local component
	for itcomponent in item.Components do
		if itcomponent.Name == componentName then
			component = itcomponent
			break
		end
	end
	if not component then
		MyModGlobal.debugPrint("No " .. componentName .. " component found")
		return
	end

	return item, component
end

---@param force boolean
local function tryAccessFabricator(force)
	local fabricator = cachedFabricator
	if not fabricator or force then
		fabricator = findByComponent("fabricator", "Fabricator")
		if not fabricator then
			MyModGlobal.debugPrint("No fabricator found")
			return
		end
		cachedFabricator = fabricator
	end

	MyModGlobal.debugPrint("Selecting fabricator")
	select(fabricator)
end

---@param force boolean
local function tryAccessDeconstructor(force)
	local deconstructor = cachedDeconstructor
	if not deconstructor or force then
		deconstructor = findByComponent("deconstructor", "Deconstructor")
		if not deconstructor then
			MyModGlobal.debugPrint("No deconstructor found")
			return
		end
		cachedDeconstructor = deconstructor
	end

	MyModGlobal.debugPrint("Selecting deconstructor")
	select(deconstructor)
end

---@param force boolean
local function tryAccessMedicalFabricator(force)
	local medicalFabricator = cachedMedicalFabricator
	if not medicalFabricator or force then
		medicalFabricator = findByComponent("medicalfabricator", "MedicalFabricator")
		if not medicalFabricator then
			MyModGlobal.debugPrint("No medical fabricator found")
			return
		end
		cachedMedicalFabricator = medicalFabricator
	end

	MyModGlobal.debugPrint("Selecting medical fabricator")
	select(medicalFabricator)
end

return {
	tryAccessFabricator = tryAccessFabricator,
	tryAccessDeconstructor = tryAccessDeconstructor,
	tryAccessMedicalFabricator = tryAccessMedicalFabricator,
}
