-- =============================================================================
-- ETB v12.45.0 — TransmogUI/ItemRows.lua
-- =============================================================================
-- 30-pixel item row construction and pool management. Each row is a Button
-- frame with icon + name + source text + collected-status bar + interaction
-- scripts. Rows are pooled across refreshes to avoid frame-creation churn.
--
-- Extracted from the v12.44.0 monolithic TransmogUI.lua. This module owns the
-- row frame structure and pooling lifecycle. The owning TUI still owns the
-- pool table (owner.rowPool), pool-parent frame (owner.rowPoolParent), and
-- the itemRows display array (owner.itemRows) — the submodule operates on
-- these by reference.
--
-- Public API:
--   ItemRows:Create(owner, parent, index)  — build a new row inside `parent`
--                                            at row position `index`. Returns
--                                            the Button frame. Does NOT insert
--                                            into owner.rowPool — caller's job.
--   ItemRows:Acquire(owner, parent, index) — acquire from pool or create new;
--                                            also positions+sizes+shows the row
--   ItemRows:ReleasePool(owner, fromIndex) — hide and clear pool entries from
--                                            `fromIndex` onward
--
-- Owner contract — fields and methods used:
--   owner.rowPool                     (array; populated during Acquire)
--   owner.rowPoolParent               (Frame; orphan parent for hidden rows)
--   owner:ShowHoverPreview(itemData)  (called on row mouseover)
--   owner:HideHoverPreview()          (called on row mouseleave)
--   owner:SelectAppearance(itemData)  (left-click on appearance item)
--   owner:ApplySet(itemData)          (left-click on set item)
--   owner:ApplyCollectedPieces(setData, pieces)  (apply-collected button)
--   owner:ShowIncompleteSetDetail(itemData)      (incomplete set farming view)
--   owner:RefreshIncompleteSets()     (back button from detail view)
--
-- External references the row uses directly (not through owner):
--   ETB.AppearanceDetail:Toggle(itemData)  (right-click handler)
--   ETB:SafeSetTooltipItem(tooltip, itemID)  (tooltip helper, optional)
--
-- Constants (exposed as fields for external consumers):
--   ItemRows.ROW_HEIGHT  = 30
--   ItemRows.ROW_SPACING = 1
-- =============================================================================

local ADDON_NAME, NS = ...
local ETB = NS.ETB

NS.ETB.TransmogUI = NS.ETB.TransmogUI or {}
local ItemRows = {}
NS.ETB.TransmogUI.ItemRows = ItemRows

-- =============================================================================
-- Constants
-- =============================================================================

-- v15.8.14: ROW_HEIGHT bumped from 30 to 34 for clearer two-line layout.
-- The Incomplete Set Detail view stacks an item name on top of a long
-- source description ("[Feet] Boss Drop From: Emalon..."). At 30px the
-- two lines visually collided. 34px gives each line its own clean band.
ItemRows.ROW_HEIGHT = 34
ItemRows.ROW_SPACING = 1

local ROW_HEIGHT = ItemRows.ROW_HEIGHT
local ROW_SPACING = ItemRows.ROW_SPACING

-- =============================================================================
-- Row creation
-- =============================================================================

function ItemRows:Create(owner, parent, index)
    local rowWidth = 330
    if parent and parent.GetWidth then rowWidth = parent:GetWidth() - 5 end

    local row = CreateFrame("Button", nil, parent)
    row:SetSize(rowWidth, ROW_HEIGHT)
    row:SetPoint("TOPLEFT", 2, -2 - (index - 1) * (ROW_HEIGHT + ROW_SPACING))

    row.bg = row:CreateTexture(nil, "BACKGROUND")
    row.bg:SetAllPoints()
    row.bg:SetColorTexture(0.08, 0.08, 0.08, 0.6)

    row.highlight = row:CreateTexture(nil, "BACKGROUND", nil, 1)
    row.highlight:SetAllPoints()
    row.highlight:SetColorTexture(0.15, 0.25, 0.15, 0.8)
    row.highlight:Hide()

    -- Collected bar (left edge indicator)
    row.collectedBar = row:CreateTexture(nil, "ARTWORK")
    row.collectedBar:SetSize(3, ROW_HEIGHT - 4)
    row.collectedBar:SetPoint("LEFT", 0, 0)
    row.collectedBar:SetColorTexture(0.2, 0.2, 0.2, 0.3)

    row.icon = row:CreateTexture(nil, "ARTWORK")
    row.icon:SetSize(26, 26)
    row.icon:SetPoint("LEFT", 6, 0)
    row.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)

    row.iconBorder = row:CreateTexture(nil, "OVERLAY")
    row.iconBorder:SetSize(28, 28)
    row.iconBorder:SetPoint("CENTER", row.icon, "CENTER")
    row.iconBorder:SetTexture("Interface\\Common\\WhiteIconFrame")

    row.name = row:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    -- v15.8.14: anchor TOPLEFT instead of LEFT so the name text sits in
    -- the upper half of the row, leaving the lower half cleanly for the
    -- source line. Previously LEFT-anchored at y=1 caused the name's
    -- descenders to overlap the source line in dense set-detail views.
    row.name:SetPoint("TOPLEFT", row.icon, "TOPRIGHT", 6, -1)
    row.name:SetPoint("RIGHT", row, "RIGHT", -8, 0)
    row.name:SetJustifyH("LEFT")
    row.name:SetJustifyV("TOP")
    row.name:SetMaxLines(1)
    row.name:SetWordWrap(false)

    row.source = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    row.source:SetPoint("BOTTOMLEFT", row.icon, "BOTTOMRIGHT", 6, 1)
    row.source:SetPoint("RIGHT", row, "RIGHT", -8, 0)
    row.source:SetJustifyH("LEFT")
    row.source:SetJustifyV("BOTTOM")
    row.source:SetTextColor(0.4, 0.4, 0.4)
    row.source:SetMaxLines(1)
    row.source:SetWordWrap(false)

    -- Status mark (hidden by default - only used when needed)
    row.status = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    row.status:SetPoint("RIGHT", -4, 0)

    -- OnEnter: highlight + hover preview + tooltip
    row:SetScript("OnEnter", function(self)
        self.highlight:Show()
        if self.itemData then
            owner:ShowHoverPreview(self.itemData)
            GameTooltip:SetOwner(self, "ANCHOR_LEFT")
            if self.itemData.itemID then
                -- v12.46.0: fixed latent bug (the guard used to check a
                -- nonexistent global `ETB_SafeSetTooltipItem` instead of the
                -- actual method on ETB). Now the rich hyperlink tooltip path
                -- actually fires for cached items.
                local ok = ETB.SafeSetTooltipItem and ETB:SafeSetTooltipItem(GameTooltip, self.itemData.itemID)
                if not ok then
                    GameTooltip:SetText(self.itemData.name or "Unknown")
                end
            else
                GameTooltip:SetText(self.itemData.name or "Unknown")
            end
            GameTooltip:Show()
        end
    end)

    row:SetScript("OnLeave", function(self)
        self.highlight:Hide()
        owner:HideHoverPreview()
        GameTooltip:Hide()
    end)

    -- OnClick: dispatch based on itemData shape
    row:SetScript("OnClick", function(self, button)
        if not self.itemData then return end
        if self.itemData.isLoadingHint then return end  -- Don't click loading hints

        if button == "RightButton" then
            -- Right-click: Show "Items That Share This Appearance" panel
            if ETB.AppearanceDetail then
                ETB.AppearanceDetail:Toggle(self.itemData)
            end
        elseif self.itemData.isApplyCollectedButton then
            -- Apply only the collected pieces from an incomplete set
            owner:ApplyCollectedPieces(self.itemData.setData, self.itemData.pieces)
        elseif self.itemData.isIncompleteSet then
            -- Incomplete set: show farming detail view
            owner:ShowIncompleteSetDetail(self.itemData)
        elseif self.itemData.isBackButton then
            -- Back button in incomplete detail view: return to list
            owner:RefreshIncompleteSets()
        elseif self.itemData.isSet then
            owner:ApplySet(self.itemData)
        else
            owner:SelectAppearance(self.itemData)
        end
    end)

    row:RegisterForClicks("LeftButtonUp", "RightButtonUp")

    return row
end

-- =============================================================================
-- Pool acquire / release
-- =============================================================================

function ItemRows:Acquire(owner, parent, index)
    local row
    if index <= #owner.rowPool then
        row = owner.rowPool[index]
    else
        row = self:Create(owner, owner.rowPoolParent or parent, index)
        table.insert(owner.rowPool, row)
    end
    local rowWidth = math.max(100, (parent:GetWidth() or 330) - 5)
    row:SetParent(parent)
    row:SetSize(rowWidth, ROW_HEIGHT)
    row:SetPoint("TOPLEFT", 2, -2 - (index - 1) * (ROW_HEIGHT + ROW_SPACING))
    row:Show()
    return row
end

function ItemRows:ReleasePool(owner, fromIndex)
    for i = fromIndex, #owner.rowPool do
        local r = owner.rowPool[i]
        r:Hide()
        r:SetParent(owner.rowPoolParent)
        r.itemData = nil
    end
end
