local addonName, ns = ...

------------------------------------------------------------
-- News tab: a 2x2 grid of article cards over ns.ARTICLES.
-- Clicking a card opens the copy popup with the article URL
-- (WoW cannot open a browser).
------------------------------------------------------------

local MEDIA_PATH = "Interface\\AddOns\\HousingHerald\\media\\articles\\"
local CARD_W, CARD_H = 278, 190
local CARD_GAP = 10
local IMG_H = 130
-- The darkened strip the overlaid title sits in. It holds near full strength
-- across the head, where the title starts, then fades away over the rest of
-- the card: a single slope left the tail of a long title on almost no backing,
-- and was too weak overall for a brightly-lit screenshot.
local TITLE_SCRIM_H = 30
local SCRIM_HEAD_W = 60
local SCRIM_ALPHA_START = 0.8   -- left edge
local SCRIM_ALPHA_MID = 0.6     -- at SCRIM_HEAD_W, where the two slopes meet
local SCRIM_ALPHA_END = 0.1     -- right edge
-- Fixed height reserved for the byline. The summary used to anchor to the
-- byline fontstring's bottom, which made its position depend on that string's
-- measured height -- one card's summary sat a whole line lower than the rest.
local AUTHOR_H = 14
-- Breathing room between the byline and the summary. Part of the summary's
-- offset from the card, not padding hung off the byline, so it stays equal on
-- every card.
local SUMMARY_GAP = 4
-- Two lines' worth of space for the summary. Pinned, like the byline: a
-- FontString left to size itself reserves room for the FULL text, and the
-- long summaries wrap past the two lines they are allowed to draw.
local SUMMARY_H = 26

-- Draw order inside a card, bottom to top: the screenshot, the scrim directly
-- over it, then the text. The first two share the ARTWORK layer and are
-- separated by sub-level; the text sits on OVERLAY, which is above ARTWORK
-- entirely. Both sub-levels are set explicitly rather than left to default, so
-- the stack is stated rather than inferred.
local IMAGE_SUBLEVEL = 0
local SCRIM_SUBLEVEL = 1

local cards = {}
ns._newsCards = cards

local function CreateCard(parent, index)
    local card = CreateFrame("Button", nil, parent, "BackdropTemplate")
    card:SetSize(CARD_W, CARD_H)
    local col = (index - 1) % 2
    local row = math.floor((index - 1) / 2)
    card:SetPoint("TOPLEFT", col * (CARD_W + CARD_GAP), -row * (CARD_H + CARD_GAP))
    card:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        edgeSize = 12,
        insets = { left = 2, right = 2, top = 2, bottom = 2 },
    })
    card:SetBackdropColor(ns.Theme.PANEL:GetRGBA())
    card:SetBackdropBorderColor(ns.Theme.BORDER:GetRGBA())

    card.image = card:CreateTexture(nil, "ARTWORK", nil, IMAGE_SUBLEVEL)
    card.image:SetPoint("TOPLEFT", 4, -4)
    card.image:SetPoint("TOPRIGHT", -4, -4)
    card.image:SetHeight(IMG_H)

    -- The title sits ON the image, so it has to stay readable over whatever the
    -- screenshot happens to be -- several are bright. Darken the strip it
    -- occupies, heaviest behind the text and thinning out to the right.
    --
    -- Two sections, because a texture carries ONE linear gradient and this
    -- scrim has two slopes. Each is a full-height rectangle pinned by two
    -- corners, the same shape as the single scrim that renders correctly --
    -- an earlier build using many narrow slices did not draw at all.
    local function scrimSection(fromAlpha, toAlpha)
        local tex = card:CreateTexture(nil, "ARTWORK", nil, SCRIM_SUBLEVEL)
        -- SetGradient modulates the vertex colour, so the base is painted white.
        tex:SetColorTexture(1, 1, 1, 1)
        if tex.SetGradient and CreateColor then
            -- HORIZONTAL: min at the left, max at the right.
            pcall(tex.SetGradient, tex, "HORIZONTAL",
                CreateColor(0, 0, 0, fromAlpha), CreateColor(0, 0, 0, toAlpha))
        end
        return tex
    end

    -- Head: strong and nearly flat, behind where the title starts.
    card.titleScrim = scrimSection(SCRIM_ALPHA_START, SCRIM_ALPHA_MID)
    card.titleScrim:SetPoint("BOTTOMLEFT", card.image, "BOTTOMLEFT", 0, 0)
    card.titleScrim:SetPoint("TOPRIGHT", card.image, "BOTTOMLEFT", SCRIM_HEAD_W, TITLE_SCRIM_H)

    -- Tail: picks up exactly where the head leaves off and fades out.
    card.titleScrimTail = scrimSection(SCRIM_ALPHA_MID, SCRIM_ALPHA_END)
    card.titleScrimTail:SetPoint("BOTTOMLEFT", card.image, "BOTTOMLEFT", SCRIM_HEAD_W, 0)
    card.titleScrimTail:SetPoint("TOPRIGHT", card.image, "BOTTOMRIGHT", 0, TITLE_SCRIM_H)

    card.titleScrimSections = { card.titleScrim, card.titleScrimTail }

    card.title = card:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    card.title:SetPoint("BOTTOMLEFT", card.image, "BOTTOMLEFT", 6, 5)
    card.title:SetPoint("RIGHT", card.image, "RIGHT", -6, 0)
    card.title:SetJustifyH("LEFT")
    card.title:SetWordWrap(false)
    card.title:SetMaxLines(1)
    card.title:SetTextColor(ns.Theme.HEADING:GetRGBA())

    -- Byline sits just below the image, in the same gold as the title. It and
    -- the summary anchor to the image -- the title's reference frame -- with
    -- the title's own 6px inset, so all three share one left edge; measured
    -- from the card they'd sit 4px (the image inset) further left.
    card.author = card:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    card.author:SetPoint("TOPLEFT", card.image, "BOTTOMLEFT", 6, -4)
    card.author:SetPoint("RIGHT", card.image, "RIGHT", -6, 0)
    card.author:SetJustifyH("LEFT")
    -- FontStrings default to MIDDLE vertical justification, which centres the
    -- drawn lines inside the box and pushes them down when the box is taller
    -- than they are -- it reads as a blank line above the text.
    card.author:SetJustifyV("TOP")
    card.author:SetWordWrap(false)
    card.author:SetMaxLines(1)
    card.author:SetHeight(AUTHOR_H)
    card.author:SetTextColor(ns.Theme.HEADING:GetRGBA())

    card.summary = card:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    card.summary:SetPoint("TOPLEFT", card.image, "BOTTOMLEFT", 6, -(4 + AUTHOR_H + SUMMARY_GAP))
    card.summary:SetPoint("RIGHT", card.image, "RIGHT", -6, 0)
    card.summary:SetJustifyH("LEFT")
    card.summary:SetJustifyV("TOP")
    card.summary:SetHeight(SUMMARY_H)
    card.summary:SetMaxLines(2)
    card.summary:SetTextColor(ns.Theme.TEXT_MUTED:GetRGBA())

    card:SetScript("OnEnter", function(self)
        self:SetBackdropBorderColor(ns.Theme.HEADING:GetRGBA())
    end)
    card:SetScript("OnLeave", function(self)
        self:SetBackdropBorderColor(ns.Theme.BORDER:GetRGBA())
    end)
    card:SetScript("OnClick", function(self)
        if self.article and ns.ShowCopyPopup then
            ns:ShowCopyPopup(self.article.url)
        end
    end)
    return card
end

local footer

function ns:RefreshNewsTab()
    local parent = ns.newsPanel
    if not parent then return end

    for i, article in ipairs(ns.ARTICLES or {}) do
        local card = cards[i]
        if not card then
            card = CreateCard(parent, i)
            cards[i] = card
        end
        card.article = article
        card.image:SetTexture(MEDIA_PATH .. article.image .. ".png")
        card.title:SetText(article.title)
        card.author:SetText(article.author and ("by " .. article.author) or "")
        card.summary:SetText(article.summary)
        card:Show()
    end

    if not footer then
        footer = parent:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
        footer:SetPoint("BOTTOM", 0, 2)
        footer:SetTextColor(ns.Theme.TEXT_MUTED:GetRGBA())
        ns._newsFooter = footer
    end
    footer:SetText(("Articles as of %s — newer may be on housing-herald.com")
        :format(ns.ARTICLES_FETCHED_AT or "?"))
end
