--[[
    Commander 3.0 - TUI Renderer

    Bridge between TuiBuffer and VirtualListRenderer.
    Creates a FontString overlay for TUI mode rendering.

    When TUI mode is active:
    1. Normal output display is hidden
    2. TUI overlay with FontString pool is shown
    3. Buffer.ToLines() output is rendered to FontStrings

    Rendering is top-down (row 1 at top) unlike the normal
    bottom-up terminal output.
]]

local ADDON_NAME, C3 = ...

-------------------------------------------------------------------------------
-- TUI Renderer
-------------------------------------------------------------------------------

local TuiRenderer = C3.class()
C3.TUI = C3.TUI or {}
C3.TUI.Renderer = TuiRenderer

-- Default configuration
local DEFAULT_MAX_ROWS = 60
local DEFAULT_CHAR_WIDTH_RATIO = 0.6  -- Approximate char width / font size

---Create a new TUI renderer
---@param terminal table TerminalWindow instance
function TuiRenderer:init(terminal)
    self.terminal = terminal
    self.overlay = nil
    self.fontStrings = {}
    self.visible = false

    -- Cached dimensions
    self._cols = 80
    self._rows = 24
    self._fontSize = 12
    self._lineHeight = 15
    self._fontPath = nil
end

---Create the TUI overlay frame with FontString pool
function TuiRenderer:_createOverlay()
    if self.overlay then return end

    local parent = self.terminal.content
    if not parent then
        C3:Debug("TuiRenderer: No terminal content frame")
        return
    end

    -- Create overlay frame
    local overlay = CreateFrame("Frame", nil, parent)
    overlay:SetAllPoints()
    overlay:SetFrameLevel(parent:GetFrameLevel() + 10)
    overlay:Hide()

    self.overlay = overlay
    self.fontStrings = {}

    -- Get theme settings
    self:_updateFontSettings()

    -- Create FontString pool
    self:_createFontStrings(DEFAULT_MAX_ROWS)
end

---Update font settings from theme
function TuiRenderer:_updateFontSettings()
    local Theme = C3.UI and C3.UI.Theme

    if Theme then
        self._fontSize = Theme:GetEffectiveFontSize() or 12
        self._lineHeight = Theme:GetEffectiveLineHeight() or 15
        self._fontPath = Theme.Font
    else
        self._fontSize = 12
        self._lineHeight = 15
        self._fontPath = "Fonts\\FRIZQT__.TTF"
    end
end

---Create FontStrings for rendering
---@param maxRows number Maximum number of rows
function TuiRenderer:_createFontStrings(maxRows)
    if not self.overlay then return end

    -- Clear existing
    for _, fs in ipairs(self.fontStrings) do
        fs:Hide()
        fs:SetText("")
    end
    self.fontStrings = {}

    -- Create new FontStrings
    for i = 1, maxRows do
        local fs = self.overlay:CreateFontString(nil, "OVERLAY", "GameFontNormal")

        -- Set font
        fs:SetFont(self._fontPath, self._fontSize, "")
        fs:SetShadowOffset(0, 0)
        fs:SetJustifyH("LEFT")
        fs:SetJustifyV("TOP")
        fs:SetWordWrap(false)
        fs:SetNonSpaceWrap(false)

        -- Position from TOP going DOWN (TUI is top-to-bottom)
        local yOffset = -(i - 1) * self._lineHeight
        fs:SetPoint("TOPLEFT", self.overlay, "TOPLEFT", 0, yOffset)
        fs:SetPoint("RIGHT", self.overlay, "RIGHT", 0, 0)
        fs:SetHeight(self._lineHeight)
        fs:Hide()

        self.fontStrings[i] = fs
    end
end

---Calculate buffer dimensions from terminal size
---@return number cols, number rows
function TuiRenderer:GetBufferSize()
    local content = self.terminal.content
    if not content then return 80, 24 end

    self:_updateFontSettings()

    local width = content:GetWidth() or 600
    local height = content:GetHeight() or 400

    -- Estimate character width (monospace assumption)
    local charWidth = self._fontSize * DEFAULT_CHAR_WIDTH_RATIO

    local cols = math.floor(width / charWidth)
    local rows = math.floor(height / self._lineHeight)

    -- Clamp to reasonable values
    cols = math.max(20, math.min(cols, 200))
    rows = math.max(5, math.min(rows, DEFAULT_MAX_ROWS))

    self._cols = cols
    self._rows = rows

    return cols, rows
end

---Render a TuiBuffer to the overlay
---@param buffer table TuiBuffer
function TuiRenderer:Render(buffer)
    if not buffer then return end

    -- Ensure overlay exists
    if not self.overlay then
        self:_createOverlay()
    end
    if not self.overlay then return end

    -- Convert buffer to lines
    local lines = buffer:ToLines()

    -- Update FontStrings
    for i, fs in ipairs(self.fontStrings) do
        if i <= #lines then
            fs:SetText(lines[i])
            fs:Show()
        else
            fs:SetText("")
            fs:Hide()
        end
    end
end

---Show the TUI overlay (and hide normal output)
function TuiRenderer:Show()
    if not self.overlay then
        self:_createOverlay()
    end
    if not self.overlay then return end

    self.overlay:Show()
    self.visible = true

    -- Hide normal output display
    if self.terminal.output then
        self.terminal.output:SetRendererVisible(false)
    end

    C3:Debug("TuiRenderer: Overlay shown")
end

---Hide the TUI overlay (and restore normal output)
function TuiRenderer:Hide()
    if self.overlay then
        self.overlay:Hide()
    end
    self.visible = false

    -- Restore normal output display
    if self.terminal.output then
        self.terminal.output:SetRendererVisible(true)
        self.terminal.output:Refresh()
    end

    C3:Debug("TuiRenderer: Overlay hidden")
end

---Check if visible
---@return boolean
function TuiRenderer:IsVisible()
    return self.visible
end

---Update font settings and recreate FontStrings if needed
function TuiRenderer:UpdateFont()
    self:_updateFontSettings()

    if self.overlay and #self.fontStrings > 0 then
        for _, fs in ipairs(self.fontStrings) do
            fs:SetFont(self._fontPath, self._fontSize, "")
        end

        -- Reposition all FontStrings with new line height
        for i, fs in ipairs(self.fontStrings) do
            fs:ClearAllPoints()
            local yOffset = -(i - 1) * self._lineHeight
            fs:SetPoint("TOPLEFT", self.overlay, "TOPLEFT", 0, yOffset)
            fs:SetPoint("RIGHT", self.overlay, "RIGHT", 0, 0)
            fs:SetHeight(self._lineHeight)
        end
    end
end

---Clear all FontStrings
function TuiRenderer:Clear()
    for _, fs in ipairs(self.fontStrings) do
        fs:SetText("")
        fs:Hide()
    end
end

---Get current dimensions
---@return number cols, number rows
function TuiRenderer:GetSize()
    return self._cols, self._rows
end

---Destroy the renderer
function TuiRenderer:Destroy()
    if self.overlay then
        for _, fs in ipairs(self.fontStrings) do
            fs:Hide()
        end
        self.fontStrings = {}
        self.overlay:Hide()
        self.overlay = nil
    end
    self.visible = false
end

return TuiRenderer
