-- [ 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 L = Orbit.L

local Tooltip = {}
Engine.SelectionTooltip = Tooltip

Tooltip.positionFadeTimer = nil

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

local DIR_LABEL = {
    LEFT = function() return L.CFG_EM_DIR_LEFT end,
    RIGHT = function() return L.CFG_EM_DIR_RIGHT end,
    TOP = function() return L.CFG_EM_DIR_TOP end,
    BOTTOM = function() return L.CFG_EM_DIR_BOTTOM end,
    CENTER = function() return L.CFG_EM_DIR_CENTER end,
}

local function LocalizeDir(token)
    local fn = token and DIR_LABEL[token]
    return fn and fn() or token
end

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

-- [ FRAME ] -----------------------------------------------------------------------------------------
-- A real GameTooltip so anchoring is EXACTLY the Blizzard/QoL pathway shared by every other tooltip; created at load so QoL/Tooltips.lua can capture it into its managed set (skin + scale parity). The template's data mixin clears manually-added lines on data-refresh events; unregister so our content persists.
Tooltip.positionTooltip = CreateFrame("GameTooltip", "OrbitPositionTooltip", UIParent, "GameTooltipTemplate")
Tooltip.positionTooltip:UnregisterAllEvents()
Tooltip.positionTooltip:Hide()

-- 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

-- One pathway with every other tooltip: GameTooltip_SetDefaultAnchor routes through the QoL anchor hook — cursor modes re-place at the pointer on each re-show (so drag updates follow), Default pins to the anchor chip, and a disabled QoL module leaves Blizzard's native default corner.
local function Present(self, text, noFade)
    local tooltip = self.positionTooltip
    GameTooltip_SetDefaultAnchor(tooltip, UIParent)
    tooltip:AddLine(text, 1, 1, 1)
    ShowAndFade(self, noFade)
end

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

    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 = L.CFG_EM_DISTANCE .. " " .. padding
    else
        -- Primary line: pixel distance from the nearest screen edge per axis (what "24px from the left" users align by); secondary dim line keeps the centre-relative X,Y many WoW layouts are built around.
        local screenW = (uiWidth * uiScale) / pixelScale
        local screenH = (uiHeight * uiScale) / pixelScale
        local left = (frameLeft * frameScale) / pixelScale
        local bottom = (frameBottom * frameScale) / pixelScale
        local right = screenW - left - (frameWidth * frameScale) / pixelScale
        local top = screenH - bottom - (frameHeight * frameScale) / pixelScale
        local edgeLine
        if relX == 0 and relY == 0 then
            edgeLine = LocalizeDir("CENTER")
        else
            local h, v
            if relX == 0 then h = LocalizeDir("CENTER")
            elseif left <= right then h = LocalizeDir("LEFT") .. " " .. math.floor(left + 0.5)
            else h = LocalizeDir("RIGHT") .. " " .. math.floor(right + 0.5) end
            if relY == 0 then v = LocalizeDir("CENTER")
            elseif bottom <= top then v = LocalizeDir("BOTTOM") .. " " .. math.floor(bottom + 0.5)
            else v = LocalizeDir("TOP") .. " " .. math.floor(top + 0.5) end
            edgeLine = h .. "  ·  " .. v
        end
        displayText = edgeLine .. "\nX " .. relX .. "  ·  Y " .. relY
    end

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

    -- Movement shows one tooltip: the frame's name rides the position readout (the hover name tooltip is hidden while dragging/nudging).
    if frame.editModeName then
        displayText = "|cffffd100" .. frame.editModeName .. "|r\n" .. displayText
    end

    Present(self, displayText, noFade)
end

-- [ SHOW LAYER TOOLTIP ] ----------------------------------------------------------------------------
-- Ctrl+scroll feedback: position in the registered layer stack plus what now sits directly below.
function Tooltip:ShowLayerInfo(frame, entityID)
    if not frame then return end
    local SE = Orbit.StrataEngine
    local index, count = SE:GetIndex("Global_HUD", entityID)
    if not index then return end
    local detail
    if index == count then
        detail = L.CFG_EM_LAYER_TOP
    elseif index == 1 then
        detail = L.CFG_EM_LAYER_BOTTOM
    else
        local below = SE:GetNeighbor("Global_HUD", entityID, -1)
        detail = L.CFG_EM_LAYER_ABOVE_F:format(SE:GetLabel("Global_HUD", below))
    end
    Present(self, L.CFG_EM_LAYER_F:format(index, count) .. "\n" .. detail)
end

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

    -- Build anchor string
    local anchorStr
    if anchorX == "CENTER" and anchorY == "CENTER" then
        anchorStr = LocalizeDir("CENTER")
    elseif anchorY == "CENTER" then
        anchorStr = LocalizeDir(anchorX)
    elseif anchorX == "CENTER" then
        anchorStr = LocalizeDir(anchorY)
    else
        anchorStr = LocalizeDir(anchorX) .. " " .. LocalizeDir(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 = LocalizeDir(justifyH or "CENTER") .. (justifyV and (", " .. LocalizeDir(justifyV)) or "")

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

    Present(self, tooltipText)
end

-- [ SHOW RESIZE INFO TOOLTIP ] ----------------------------------------------------------------------
function Tooltip:ShowResizeInfo(frame, width, height, noFade)
    if not frame then return end
    Present(self, string.format("%d × %d", width, height), noFade)
end
