YarderTowerHUDExtension = {
	MOD_NAME = g_currentModName,
	MOD_DIR = g_currentModDirectory
}
YarderTowerHUDExtension.GUI_ELEMENTS = YarderTowerHUDExtension.MOD_DIR .. "hud/ui_elements.png"
local YarderTowerHUDExtension_mt = Class(YarderTowerHUDExtension, VehicleHUDExtension)

function YarderTowerHUDExtension.new(vehicle, uiScale, uiTextColor, uiTextSize)
	local self = VehicleHUDExtension.new(YarderTowerHUDExtension_mt, vehicle, uiScale, uiTextColor, uiTextSize)
	self.uiTextColor = uiTextColor
	_, self.textHeightHeadline = getNormalizedScreenValues(0, 17 * uiScale)
	_, self.infoTextHeight = getNormalizedScreenValues(0, 16 * uiScale)
	self.textMaxWidthHeadline, _ = getNormalizedScreenValues(440 * uiScale, 0)
	local width, height = getNormalizedScreenValues(440 * uiScale, 63 * uiScale)
	self.background = Overlay.new(YarderTowerHUDExtension.GUI_ELEMENTS, 0, 0, width, height)

	self.background:setUVs(GuiUtils.getUVs(YarderTowerHUDExtension.UV.BACKGROUND))
	self.background:setColor(unpack(YarderTowerHUDExtension.COLOR.MAIN_COLOR))
	self:addComponentForCleanup(self.background)

	width, height = getNormalizedScreenValues(32 * uiScale, 32 * uiScale)
	self.carriageFull = Overlay.new(YarderTowerHUDExtension.GUI_ELEMENTS, 0, 0, width, height)

	self.carriageFull:setUVs(GuiUtils.getUVs(YarderTowerHUDExtension.UV.CARRIAGE_FULL))
	self.carriageFull:setColor(unpack(YarderTowerHUDExtension.COLOR.THIRD_COLOR))
	self:addComponentForCleanup(self.carriageFull)

	self.carriageEmpty = Overlay.new(YarderTowerHUDExtension.GUI_ELEMENTS, 0, 0, width, height)

	self.carriageEmpty:setUVs(GuiUtils.getUVs(YarderTowerHUDExtension.UV.CARRIAGE_EMPTY))
	self.carriageEmpty:setColor(unpack(YarderTowerHUDExtension.COLOR.THIRD_COLOR))
	self:addComponentForCleanup(self.carriageEmpty)

	width, height = getNormalizedScreenValues(25 * uiScale, 25 * uiScale)
	self.player = Overlay.new(YarderTowerHUDExtension.GUI_ELEMENTS, 0, 0, width, height)

	self.player:setUVs(GuiUtils.getUVs(YarderTowerHUDExtension.UV.PLAYER))
	self.player:setColor(unpack(YarderTowerHUDExtension.COLOR.SECOND_COLOR))
	self:addComponentForCleanup(self.player)

	width, height = getNormalizedScreenValues(18 * uiScale, 18 * uiScale)
	self.targetPositionMarker = Overlay.new(YarderTowerHUDExtension.GUI_ELEMENTS, 0, 0, width, height)

	self.targetPositionMarker:setUVs(GuiUtils.getUVs(YarderTowerHUDExtension.UV.PLAYER))
	self.targetPositionMarker:setColor(unpack(YarderTowerHUDExtension.COLOR.SECOND_COLOR))
	self:addComponentForCleanup(self.targetPositionMarker)

	-- Carriage camera (picture-in-picture) sized to match yarder HUD width (in pixels)
	-- Use getNormalizedScreenValues for both axes to avoid aspect-ratio distortion.
	local camWidthPx = 440 * uiScale
	local camHeightPx = camWidthPx * (9 / 16) -- 16:9
	local camWidth, camHeight = getNormalizedScreenValues(camWidthPx, camHeightPx)
	self.carriageCam = {
		width = camWidth,
		height = camHeight,
		border = 0,
		overlayId = 0,
		camera = nil,
		linkNode = nil,
		isSupported = false
	}

	if createCamera ~= nil and createRenderOverlay ~= nil and updateRenderOverlay ~= nil and renderOverlay ~= nil then
		local resolutionX = 1024
		local resolutionY = 576
		local aspectRatio = resolutionX / resolutionY

		self.carriageCam.camera = createCamera("YarderCarriageCam", math.rad(60), 0.01, 10000)

		if createTransformGroup ~= nil then
			self.carriageCam.linkNode = createTransformGroup("YarderCarriageCamLink")
			link(getRootNode(), self.carriageCam.linkNode)
			link(self.carriageCam.linkNode, self.carriageCam.camera)
			setTranslation(self.carriageCam.camera, 0, 0, 0)
			setRotation(self.carriageCam.camera, 0, 0, 0)
		end

		self.carriageCam.overlayId = createRenderOverlay(self.carriageCam.camera, aspectRatio, resolutionX, resolutionY, true, 4294967295, 4294967295)
		self.carriageCam.isSupported = self.carriageCam.overlayId ~= 0
	end

	local _ = nil
	_, self.borderTop = getNormalizedScreenValues(0, 30 * uiScale)
	_, self.borderBottom = getNormalizedScreenValues(0, 12 * uiScale)
	self.ropeWidth = 0.775
	self.ropeHeight = 0.8809523809523809
	self.carriagePivot = 0.7962962962962963
	self.markerPivot = 0.2777777777777778
	self.playerWidth = 0.775
	self.playerHeight = 0.15
	self.texts = {
		headline = string.format("%s - %s", g_i18n:getText("helpLine_yarder", YarderTowerHUDExtension.MOD_NAME), vehicle:getName())
	}

	return self
end

function YarderTowerHUDExtension:getPriority()
	return 1
end

function YarderTowerHUDExtension:canDraw()
	return self.vehicle:getYarderIsSetUp()
end

function YarderTowerHUDExtension:getDisplayHeight()
	return self:canDraw() and self.background.height + self.borderTop + self.borderBottom or 0
end

function YarderTowerHUDExtension:getHelpEntryCountReduction()
	return 1
end

function YarderTowerHUDExtension:update(dt)
	if not self:canDraw() then
		return
	end

	if self.carriageCam == nil or not self.carriageCam.isSupported then
		return
	end

	local carriageVehicle = self.vehicle.spec_yarderTower ~= nil and self.vehicle.spec_yarderTower.carriage.vehicle or nil
	local camNode = carriageVehicle ~= nil and carriageVehicle.getCarriageHudCameraNode ~= nil and carriageVehicle:getCarriageHudCameraNode() or nil

	if camNode ~= nil and self.carriageCam.camera ~= nil and self.carriageCam.overlayId ~= 0 then
		local x, y, z = getWorldTranslation(camNode)

		if self.carriageCam.linkNode ~= nil then
			local rx, ry, rz = getWorldRotation(camNode)

			setWorldTranslation(self.carriageCam.linkNode, x, y, z)
			setWorldRotation(self.carriageCam.linkNode, rx, ry, rz)
		else
			local rx, ry, rz = getWorldRotation(camNode)

			setWorldTranslation(self.carriageCam.camera, x, y, z)
			setWorldRotation(self.carriageCam.camera, rx, ry, rz)
		end

		updateRenderOverlay(self.carriageCam.overlayId)
	end
end

function YarderTowerHUDExtension:delete()
	if self.carriageCam ~= nil then
		if self.carriageCam.camera ~= nil and delete ~= nil then
			pcall(delete, self.carriageCam.camera)
		end

		if self.carriageCam.linkNode ~= nil and delete ~= nil then
			pcall(delete, self.carriageCam.linkNode)
		end

		if self.carriageCam.overlayId ~= nil and self.carriageCam.overlayId ~= 0 and delete ~= nil then
			pcall(delete, self.carriageCam.overlayId)
		end
	end

	VehicleHUDExtension.delete(self)
end

local function renderDoubleText(x, y, textSize, text, maxWidth)
	if maxWidth ~= nil then
		while maxWidth < getTextWidth(textSize, text) do
			textSize = textSize * 0.98
		end
	end

	setTextColor(0, 0, 0, 1)
	renderText(x, y - 0.0015, textSize, text)
	setTextColor(1, 1, 1, 1)
	renderText(x, y, textSize, text)
end

function YarderTowerHUDExtension:draw(leftPosX, rightPosX, posY)
	if not self:canDraw() then
		return
	end

	local isPlayerInRange, isLoaded, playerPosition, carriagePosition, followModeState, followModeLocalPlayer, targetPosition = self.vehicle:getYarderStatusInfo()

	setTextColor(unpack(self.uiTextColor))
	setTextBold(true)
	setTextAlignment(RenderText.ALIGN_LEFT)
	renderDoubleText(leftPosX, posY + self.borderBottom + self.background.height + self.borderTop * 0.25, self.textHeightHeadline, self.texts.headline, self.textMaxWidthHeadline)
	setTextBold(false)

	local centerX = (rightPosX + leftPosX) * 0.5

	self.background:setPosition(centerX - self.background.width * 0.5, posY + self.borderBottom)
	self.background:render()

	-- Render carriage cam (if available)
	-- Place camera panel inside the yarder HUD (top-right)
	local camX = self.background.x + (self.background.width - self.carriageCam.width) * 0.5
	local camY = math.max(0, self.background.y - self.carriageCam.height - self.carriageCam.border - 0.01)
	-- no background/frame, just the camera feed

	if self.carriageCam.isSupported then
		local carriageVehicle = self.vehicle.spec_yarderTower ~= nil and self.vehicle.spec_yarderTower.carriage.vehicle or nil
		local camNode = carriageVehicle ~= nil and carriageVehicle.getCarriageHudCameraNode ~= nil and carriageVehicle:getCarriageHudCameraNode() or nil

		if camNode ~= nil and self.carriageCam.camera ~= nil and self.carriageCam.overlayId ~= 0 then
			-- Keep this fully self-contained in draw(): some HUD extension paths don't call update() reliably.
			local x, y, z = getWorldTranslation(camNode)
			local rx, ry, rz = getWorldRotation(camNode)

			if self.carriageCam.linkNode ~= nil then
				setWorldTranslation(self.carriageCam.linkNode, x, y, z)
				setWorldRotation(self.carriageCam.linkNode, rx, ry, rz)
			else
				setWorldTranslation(self.carriageCam.camera, x, y, z)
				setWorldRotation(self.carriageCam.camera, rx, ry, rz)
			end

			updateRenderOverlay(self.carriageCam.overlayId)
			renderOverlay(self.carriageCam.overlayId, camX, camY, self.carriageCam.width, self.carriageCam.height)
		end
	end

	if followModeState == YarderTower.FOLLOW_MODE_ME and followModeLocalPlayer then
		self.player:setColor(nil, nil, nil, YarderTowerHUDExtension.COLOR.MAIN_COLOR[4] * (math.sin(g_time * 0.0075) * 0.25 + 0.5))
	else
		self.player:setColor(nil, nil, nil, 1)
	end

	local ropeWidth = self.background.width * self.ropeWidth

	if targetPosition ~= nil then
		self.targetPositionMarker:setColor(nil, nil, nil, YarderTowerHUDExtension.COLOR.SECOND_COLOR[4] * (math.sin(g_time * 0.0075) * 0.25 + 0.5))

		local targetMarkerPosX = self.background.x + (self.background.width - ropeWidth) * 0.5 + ropeWidth * targetPosition - self.targetPositionMarker.width * 0.5
		local targetMarkerPosY = self.background.y + self.background.height * self.ropeHeight - self.targetPositionMarker.height * self.markerPivot

		self.targetPositionMarker:setPosition(targetMarkerPosX, targetMarkerPosY)
		self.targetPositionMarker:render()
	end

	local carriageIcon = isLoaded and self.carriageFull or self.carriageEmpty
	local carriagePosX = self.background.x + (self.background.width - ropeWidth) * 0.5 + ropeWidth * carriagePosition - carriageIcon.width * 0.5
	local carriagePosY = self.background.y + self.background.height * self.ropeHeight - carriageIcon.height * self.carriagePivot

	carriageIcon:setPosition(carriagePosX, carriagePosY)
	carriageIcon:render()

	if isPlayerInRange then
		local playerWidth = self.background.width * self.playerWidth
		local playerPosX = self.background.x + (self.background.width - playerWidth) * 0.5 + playerWidth * playerPosition - self.player.width * 0.5
		local playerPosY = self.background.y + self.background.height * self.playerHeight - self.player.height * 0.5

		self.player:setPosition(playerPosX, playerPosY)
		self.player:render()
	end

	return posY
end

YarderTowerHUDExtension.COLOR = {
	MAIN_COLOR = {
		0.0003,
		0.5647,
		0.9822,
		1
	},
	SECOND_COLOR = {
		0,
		1,
		0,
		1
	},
	THIRD_COLOR = {
		0.6,
		0,
		0,
		1
	}
}
YarderTowerHUDExtension.UV = {
	BACKGROUND = {
		8,
		47,
		440,
		63
	},
	CARRIAGE_FULL = {
		8,
		115,
		54,
		54
	},
	CARRIAGE_EMPTY = {
		67,
		115,
		54,
		54
	},
	PLAYER = {
		136,
		123,
		36,
		36
	}
}
