if not TowTruckMod then TowTruckMod = {} end
if not TowTruckMod.UI then TowTruckMod.UI = {} end

---------------------------------------------------------------------------
--- UI functions
---------------------------------------------------------------------------

function TowTruckMod.UI.addHookOptionToMenu(playerObj, vehicle)
	local menu = getPlayerRadialMenu(playerObj:getPlayerNum())
	if menu == nil then return end
	
	local flippedVehicle = TowTruckMod.Utils.getUpsideDownVehicle(vehicle)
	if #flippedVehicle == 1 then
		local centerHook = TowTruckMod.Utils.getCenterHook(vehicle, flippedVehicle[1])
		menu:addSlice(centerHook[1].name, centerHook[1].texture, centerHook[1].func, playerObj, centerHook[1].towingVehicle, centerHook[1].towedVehicle, centerHook[1].towingPoint, centerHook[1].towedPoint)
		return
	end

	local vehicles = TowTruckMod.Utils.getAviableVehicles(vehicle, false)
	if #vehicles == 1 then
		local hookTypeVariants = TowTruckMod.Utils.getHookTypeVariants(vehicle, vehicles[1], false)
		menu:addSlice(hookTypeVariants[1].name, hookTypeVariants[1].texture, hookTypeVariants[1].func, playerObj, hookTypeVariants[1].towingVehicle, hookTypeVariants[1].towedVehicle, hookTypeVariants[1].towingPoint, hookTypeVariants[1].towedPoint)	
	end
end

function TowTruckMod.UI.addUnhookOptionToMenu(playerObj, vehicle)
	local menu = getPlayerRadialMenu(playerObj:getPlayerNum())
	if menu == nil then return end

	-- Get the towed vehicle - must be actively towing something
	local towedVehicle = vehicle:getVehicleTowing()
	if not towedVehicle then return end

	local attachment = vehicle:getTowAttachmentOther()
	if not attachment then return end

	if TowTruckMod.Utils.isTrailer(towedVehicle) then
		return
	end

	local detachFunc = TowTruckMod.Hook.detachTowTruckAction
	-- Add towhook height options.
	if attachment ~= "flipNode" then
		menu:addSlice(getText("UI_Text_Towing_heightmenu"), getTexture("media/textures/arrows.png"), TowTruckMod.UI.showChooseTowHeightMenu, playerObj, vehicle, towedVehicle)
	end
	menu:addSlice(getText("UI_Text_Towing_detach", ISVehicleMenu.getVehicleDisplayName(towedVehicle)), getTexture("media/textures/untow_car_icon.png"), detachFunc, playerObj, vehicle, attachment)
end

function TowTruckMod.UI.showChooseTowHeightMenu(playerObj, towingVehicle, towedVehicle)
	-- Safety checks
	if not towingVehicle or not towedVehicle then return end
	if not towingVehicle:getVehicleTowing() then return end

	local playerIndex = playerObj:getPlayerNum()
	local menu = getPlayerRadialMenu(playerIndex)
	menu:clear()

	local modData = towingVehicle:getModData()
	modData.towHeight = modData.towHeight or -1
	towingVehicle:transmitModData()
	local towHeight = modData.towHeight
	if towHeight < 1 then -- At Min
		menu:addSlice(getText("UI_Text_Towing_heightup"), getTexture("media/textures/arrow_up.png"), TowTruckMod.Hook.adjustTowHeight, playerObj, towingVehicle, towedVehicle, 0.15)
		menu:addSlice(getText("UI_Text_Towing_heightmin"), getTexture("media/textures/arrow_down_gray.png"), TowTruckMod.Hook.fakeFunc, playerObj, towingVehicle, towedVehicle)
	elseif towHeight > 5 then -- At Max (raised from 3 to 5 for more lift)
		menu:addSlice(getText("UI_Text_Towing_heightmax"), getTexture("media/textures/arrow_up_gray.png"), TowTruckMod.Hook.fakeFunc, playerObj, towingVehicle, towedVehicle)
		menu:addSlice(getText("UI_Text_Towing_heightdown"), getTexture("media/textures/arrow_down.png"), TowTruckMod.Hook.adjustTowHeight, playerObj, towingVehicle, towedVehicle, -0.15)
	else -- Any other height
		menu:addSlice(getText("UI_Text_Towing_heightup"), getTexture("media/textures/arrow_up.png"), TowTruckMod.Hook.adjustTowHeight, playerObj, towingVehicle, towedVehicle, 0.15)
		menu:addSlice(getText("UI_Text_Towing_heightdown"), getTexture("media/textures/arrow_down.png"), TowTruckMod.Hook.adjustTowHeight, playerObj, towingVehicle, towedVehicle, -0.15)
	end

	menu:setX(getPlayerScreenLeft(playerIndex) + getPlayerScreenWidth(playerIndex) / 2 - menu:getWidth() / 2)
	menu:setY(getPlayerScreenTop(playerIndex) + getPlayerScreenHeight(playerIndex) / 2 - menu:getHeight() / 2)
	menu:addToUIManager()
	if JoypadState.players[playerObj:getPlayerNum()+1] then
		menu:setHideWhenButtonReleased(Joypad.DPadUp)
		setJoypadFocus(playerObj:getPlayerNum(), menu)
		playerObj:setJoypadIgnoreAimUntilCentered(true)
	end	
end

function TowTruckMod.UI.removeDefaultTrailerOptions(playerObj)
   local menu = getPlayerRadialMenu(playerObj:getPlayerNum())
   if menu == nil then return end

   local tmpSlices = menu.slices
   menu:clear()
   for _, slice in ipairs(tmpSlices) do
      if slice.command[1] ~= ISVehicleMenu.onAttachTrailer and slice.command[1] ~= ISVehicleMenu.onDetachTrailer then
         menu:addSlice(slice.text, slice.texture, slice.command[1], 
                        slice.command[2], slice.command[3], slice.command[4], slice.command[5], slice.command[6], slice.command[7])
      end
   end
end

---------------------------------------------------------------------------
--- Mod compability
---------------------------------------------------------------------------

if getActivatedMods():contains("vehicle_additions") then
   require('Vehicles/ISUI/Oven_Mattress_RadialMenu')
   require('Vehicles/ISUI/FuelTruckTank_ISVehicleMenu_FillPartMenu')
end

---------------------------------------------------------------------------
--- Attach to default menu method
---------------------------------------------------------------------------

-- Find the closest tow truck from a given square
local function findNearbyTowTruck(square, ignoreVehicle)
	if not square then return nil end

	local towTrucks = {}
	local searchRadius = 6

	for y = square:getY() - searchRadius, square:getY() + searchRadius do
		for x = square:getX() - searchRadius, square:getX() + searchRadius do
			local sq = getCell():getGridSquare(x, y, square:getZ())
			if sq then
				for i = 1, sq:getMovingObjects():size() do
					local obj = sq:getMovingObjects():get(i - 1)
					if obj and instanceof(obj, "BaseVehicle") and obj ~= ignoreVehicle then
						if TowTruckMod.Utils.isTowTruck(obj) then
							table.insert(towTrucks, obj)
						end
					end
				end
			end
		end
	end

	if #towTrucks == 0 then return nil end

	-- Sort by distance to find closest tow truck
	local sx, sy = square:getX(), square:getY()
	table.sort(towTrucks, function(a, b)
		local aSquare = a:getSquare()
		local bSquare = b:getSquare()
		if not aSquare or not bSquare then return false end
		local aDist = math.abs(aSquare:getX() - sx) + math.abs(aSquare:getY() - sy)
		local bDist = math.abs(bSquare:getX() - sx) + math.abs(bSquare:getY() - sy)
		return aDist < bDist
	end)

	return towTrucks[1]
end

-- Helper function to add tow truck options to a vehicle's radial menu
local function addTowTruckOptionsToMenu(playerObj, vehicle, isOutside)
	if vehicle == nil then return end

	local towTruck = nil

	-- If the interacted vehicle IS a tow truck, use it
	if TowTruckMod.Utils.isTowTruck(vehicle) then
		towTruck = vehicle
	-- If outside and interacted vehicle is NOT a tow truck, look for nearby tow truck
	elseif isOutside then
		towTruck = findNearbyTowTruck(vehicle:getSquare(), vehicle)
	end

	if not towTruck then return end

	-- Always remove vanilla trailer options when a tow truck is involved
	TowTruckMod.UI.removeDefaultTrailerOptions(playerObj)

	local towedVehicle = towTruck:getVehicleTowing()
	if towedVehicle ~= nil then
		TowTruckMod.UI.addUnhookOptionToMenu(playerObj, towTruck)
	else
		TowTruckMod.UI.addHookOptionToMenu(playerObj, towTruck)
	end
end

-- Override showRadialMenu (when INSIDE vehicle) - Build 42
local old_ISVehicleMenu_showRadialMenu = ISVehicleMenu.showRadialMenu
function ISVehicleMenu.showRadialMenu(playerObj)
	old_ISVehicleMenu_showRadialMenu(playerObj)

	-- When inside vehicle, playerObj:getVehicle() returns the vehicle
	local vehicle = playerObj:getVehicle()
	addTowTruckOptionsToMenu(playerObj, vehicle, false)
end

-- Override showRadialMenuOutside (when OUTSIDE vehicle) - Build 42
local old_ISVehicleMenu_showRadialMenuOutside = ISVehicleMenu.showRadialMenuOutside
function ISVehicleMenu.showRadialMenuOutside(playerObj)
	old_ISVehicleMenu_showRadialMenuOutside(playerObj)

	-- When outside, use getVehicleToInteractWith to find the nearby vehicle
	local vehicle = ISVehicleMenu.getVehicleToInteractWith(playerObj)
	addTowTruckOptionsToMenu(playerObj, vehicle, true)
end

