-- [ ORBIT SELECTION - POSITION TOOLTIP ] ------------------------------------------------------------
-- Handles the position tooltip shown during keyboard nudging and component editing

local _, Orbit = ...
local Engine = Orbit.Engine
local C = Orbit.Constants

local Tooltip = {}
Engine.SelectionTooltip = Tooltip

Tooltip.positionTooltip = nil
Tooltip.positionFadeTimer = nil

local ANCHOR_ALIGN_HEX = {
    LEFT = "FF8C26",
    TOP = "FF8C26",
    CENTER = "33E6D9",
    RIGHT = "A659F2",
    BOTTOM = "A659F2",
}

function Tooltip:BuildAnchorLabel(align)
    local hex = ANCHOR_ALIGN_HEX[align] or "FFFFFF"
    return "|cFF" .. hex .. "Anchor: " .. align .. "|r"
end

-- [ HELPERS ] ---------------------------------------------------------------------------------------
-- Ensure tooltip frame exists (lazy initialization)
local function EnsureTooltip(self)
    if self.positionTooltip then
        return self.positionTooltip
    end

    local tooltip = CreateFrame("Frame", "OrbitPositionTooltip", UIParent, "BackdropTemplate")
    tooltip:SetFrameStrata(Orbit.Constants.Strata.Topmost)
    Engine.Pixel:Enforce(tooltip)
    tooltip:SetSize(C.Selection.PositionTooltip.Width, C.Selection.PositionTooltip.Height)
    tooltip:SetBackdrop({
        bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true,
        tileSize = 16,
        edgeSize = 12,
        insets = { left = 2, right = 2, top = 2, bottom = 2 },
    })
    tooltip:SetBackdropColor(0, 0, 0, 0.9)
    tooltip:SetBackdropBorderColor(0.3, 0.3, 0.3, 1)

    tooltip.text = tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    tooltip.text:SetPoint("CENTER")
    tooltip.text:SetTextColor(1, 1, 1, 1)

    tooltip:Hide()
    self.positionTooltip = tooltip
    return tooltip
end

-- Position tooltip at cursor with screen edge awareness
-- @param anchor: "BOTTOMRIGHT" (default), "LEFT", or "RIGHT"
local function PositionAtCursor(tooltip, anchor)
    local cursorX, cursorY = GetCursorPosition()
    local uiScale = UIParent:GetEffectiveScale()
    cursorX = cursorX / uiScale
    cursorY = cursorY / uiScale

    local tooltipWidth = tooltip:GetWidth()
    local tooltipHeight = tooltip:GetHeight()
    local screenWidth = GetScreenWidth()

    tooltip:ClearAllPoints()

    if anchor == "LEFT" then
        tooltip:SetPoint("RIGHT", UIParent, "BOTTOMLEFT", Engine.Pixel:Snap(cursorX - 20, uiScale), Engine.Pixel:Snap(cursorY, uiScale))
    elseif anchor == "RIGHT" then
        tooltip:SetPoint("LEFT", UIParent, "BOTTOMLEFT", Engine.Pixel:Snap(cursorX + 20, uiScale), Engine.Pixel:Snap(cursorY, uiScale))
    else
        local pad = 24 / uiScale
        local targetX = math.min(cursorX + pad, screenWidth - tooltipWidth - 2)
        local targetY = math.max(cursorY - pad, tooltipHeight + 2)
        tooltip:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", Engine.Pixel:Snap(targetX, uiScale), Engine.Pixel:Snap(targetY, uiScale))
    end
end

-- Show tooltip and manage fade timer
local function ShowAndFade(self, noFade)
    self.positionTooltip:SetAlpha(1)
    self.positionTooltip:Show()

    -- Cancel existing fade timer
    if self.positionFadeTimer then
        self.positionFadeTimer:Cancel()
        self.positionFadeTimer = nil
    end

    if noFade then
        return
    end

    -- Start fade out after delay
    self.positionFadeTimer = C_Timer.NewTimer(C.Selection.TooltipFadeDuration, function()
        if self.positionTooltip then
            UIFrameFadeOut(self.positionTooltip, C.Timing.FadeDuration, 1, 0)
        end
        self.positionFadeTimer = nil
    end)
end

-- [ SHOW FRAME POSITION TOOLTIP ] -------------------------------------------------------------------
function Tooltip:ShowPosition(frame, Selection, noFade, anchorLabel)
    if not frame then
        return
    end

    local tooltip = EnsureTooltip(self)

    local uiScale = UIParent:GetEffectiveScale()
    local uiWidth, uiHeight = UIParent:GetWidth(), UIParent:GetHeight()
    local screenCenterX = (uiWidth * uiScale) / 2
    local screenCenterY = (uiHeight * uiScale) / 2

    local frameLeft, frameBottom, frameWidth, frameHeight = frame:GetRect()
    if not frameLeft then
        return
    end

    local frameScale = frame:GetEffectiveScale()
    local frameCenterX = (frameLeft + (frameWidth / 2)) * frameScale
    local frameCenterY = (frameBottom + (frameHeight / 2)) * frameScale

    local pixelScale = Engine.Pixel and Engine.Pixel:GetScale() or 1
    local relX = math.floor((frameCenterX - screenCenterX) / pixelScale + 0.5)
    local relY = math.floor((frameCenterY - screenCenterY) / pixelScale + 0.5)

    local parent = Engine.FrameAnchor:GetAnchorParent(frame)
    local displayText
    if parent then
        local anchor = Engine.FrameAnchor.anchors[frame]
        local padding = anchor and anchor.padding or 0
        displayText = "Distance: " .. padding
    else
        displayText = string.format("%d, %d", relX, relY)
    end

    if anchorLabel then
        displayText = displayText .. "\n" .. anchorLabel
    end

    tooltip.text:SetText(displayText)

    local textWidth = tooltip.text:GetStringWidth()
    local textHeight = tooltip.text:GetStringHeight()
    tooltip:SetSize(textWidth + 16, textHeight + 12)

    PositionAtCursor(tooltip, nil)

    ShowAndFade(self, noFade)
end

-- [ SHOW COMPONENT POSITION TOOLTIP ] ---------------------------------------------------------------
function Tooltip:ShowComponentPosition(component, key, anchorX, anchorY, posX, posY, offsetX, offsetY, justifyH, justifyV)
    if not component then
        return
    end

    local tooltip = EnsureTooltip(self)

    -- Build anchor string
    local anchorStr
    if anchorX == "CENTER" and anchorY == "CENTER" then
        anchorStr = "CENTER"
    elseif anchorY == "CENTER" then
        anchorStr = anchorX
    elseif anchorX == "CENTER" then
        anchorStr = anchorY
    else
        anchorStr = anchorX .. " " .. anchorY
    end

    -- Format display values
    local displayOffX = math.floor((offsetX or 0) + 0.5)
    local displayOffY = math.floor((offsetY or 0) + 0.5)
    local displayPosX = math.floor((posX or 0) + 0.5)
    local displayPosY = math.floor((posY or 0) + 0.5)
    local justifyStr = (justifyH or "CENTER") .. (justifyV and (", " .. justifyV) or "")

    -- Build tooltip text based on anchor type
    local tooltipText
    if anchorX == "CENTER" and anchorY == "CENTER" then
        tooltipText = string.format("%s\nJustify: %s\nPosition: %d, %d", anchorStr, justifyStr, displayPosX, displayPosY)
    else
        tooltipText = string.format("%s\nJustify: %s\nOffset: %d, %d", anchorStr, justifyStr, displayOffX, displayOffY)
    end

    tooltip.text:SetText(tooltipText)

    -- Resize tooltip to fit text
    local textWidth = tooltip.text:GetStringWidth()
    local textHeight = tooltip.text:GetStringHeight()
    tooltip:SetSize(textWidth + 16, textHeight + 12)

    PositionAtCursor(tooltip, "BOTTOMRIGHT")
    ShowAndFade(self)
end

-- [ SHOW RESIZE INFO TOOLTIP ] ----------------------------------------------------------------------
function Tooltip:ShowResizeInfo(frame, width, height, noFade)
    if not frame then return end
    local tooltip = EnsureTooltip(self)
    tooltip.text:SetText(string.format("%d × %d", width, height))
    local textWidth = tooltip.text:GetStringWidth()
    local textHeight = tooltip.text:GetStringHeight()
    tooltip:SetSize(textWidth + 16, textHeight + 12)
    PositionAtCursor(tooltip, "BOTTOMRIGHT")
    ShowAndFade(self, noFade)
end
