local RUI = LibStub("RUI-1.0")
if not RUI then return end

-- RUI.Widget.FontDropdown(parent, label, x, y, width, get, set, lsm [,onSet] [,ddName])
-- → Button, Refresh()
-- Searchable font picker: closed button renders the selected font name in that font.
-- Open menu has a search box at the top; each row renders in its own font face.
-- Total height consumed: LABEL_H(14) + DD_H(24) + CONTROL_GAP(4) = 42px.

local SEARCH_H     = 26   -- height of the search bar area at top of popup
local MENU_ROW_H   = 24   -- taller than generic 22 to accommodate variable font metrics
local MENU_MAX_VIS = 10   -- max visible rows before scrolling

function RUI.Widget.FontDropdown(parent, label, x, y, width, get, set, lsm, onSet, ddName)
    local lbl = RUI.Draw.MakeLabel(parent)
    lbl:SetTextColor(RUI.C.TEXT.r, RUI.C.TEXT.g, RUI.C.TEXT.b)
    lbl:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)
    lbl:SetWidth(width)
    lbl:SetJustifyH("LEFT")
    lbl:SetText(label)

    local btn = RUI.Draw.MakeDropdownButton(parent, ddName, width)
    btn:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y - RUI.LABEL_H)

    -- ── Custom menu popup (not from MakeMenuFrame — needs a search box above scroll) ──

    local menuFrame = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
    menuFrame:SetFrameStrata("FULLSCREEN_DIALOG")
    menuFrame:SetClampedToScreen(true)
    menuFrame:SetBackdrop({
        bgFile   = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 1,
    })
    menuFrame:SetBackdropColor(RUI.C.PANEL.r, RUI.C.PANEL.g, RUI.C.PANEL.b, 0.98)
    menuFrame:SetBackdropBorderColor(RUI.C.BORDER.r, RUI.C.BORDER.g, RUI.C.BORDER.b, 1)
    menuFrame:Hide()

    -- Search box
    local searchBox = CreateFrame("EditBox", nil, menuFrame, "BackdropTemplate")
    searchBox:SetPoint("TOPLEFT",  menuFrame, "TOPLEFT",  4, -4)
    searchBox:SetPoint("TOPRIGHT", menuFrame, "TOPRIGHT", -4, -4)
    searchBox:SetHeight(22)
    searchBox:SetAutoFocus(false)
    searchBox:SetFontObject(GameFontHighlightSmall)
    searchBox:SetTextInsets(8, 8, 0, 0)
    searchBox:SetMaxLetters(64)
    searchBox:SetBackdrop({
        bgFile   = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 1,
    })
    searchBox:SetBackdropColor(RUI.C.BG.r, RUI.C.BG.g, RUI.C.BG.b, 1)
    searchBox:SetBackdropBorderColor(RUI.C.BORDER.r, RUI.C.BORDER.g, RUI.C.BORDER.b, 1)

    -- Placeholder text (hidden while focused or when text present)
    local placeholder = searchBox:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    placeholder:SetPoint("LEFT", searchBox, "LEFT", 8, 0)
    placeholder:SetText("Search fonts...")
    placeholder:SetTextColor(RUI.C.DIM.r, RUI.C.DIM.g, RUI.C.DIM.b)

    searchBox:SetScript("OnEditFocusGained", function()
        placeholder:Hide()
    end)
    searchBox:SetScript("OnEditFocusLost", function()
        if searchBox:GetText() == "" then placeholder:Show() end
    end)
    searchBox:SetScript("OnEscapePressed", function()
        menuFrame:Hide()
    end)

    -- Scroll frame — starts below the search box
    local scrollFrame = CreateFrame("ScrollFrame", nil, menuFrame, "ScrollFrameTemplate")
    scrollFrame:SetPoint("TOPLEFT",     menuFrame, "TOPLEFT",     2,   -(SEARCH_H + 4))
    scrollFrame:SetPoint("BOTTOMRIGHT", menuFrame, "BOTTOMRIGHT", -20, 2)

    local scrollChild = CreateFrame("Frame", nil, scrollFrame)
    local rowW = width - 22
    scrollChild:SetWidth(rowW)
    scrollFrame:SetScrollChild(scrollChild)

    RUI.Draw.StyleMenuScrollBar(scrollFrame)

    menuFrame:SetScript("OnHide", function()
        if RUI._openMenu == menuFrame then RUI._openMenu = nil end
        searchBox:SetText("")
        searchBox:ClearFocus()
        placeholder:Show()
    end)

    -- ── Row management ────────────────────────────────────────────────────────

    local rows = {}

    local function UpdateButtonText()
        btn.Text:SetFontObject(GameFontHighlightSmall)
        btn.Text:SetText(get() or "")
    end

    local function RebuildRows(filterText)
        for _, r in ipairs(rows) do r:Hide(); r:SetParent(nil) end
        wipe(rows)

        filterText = filterText and filterText:lower() or ""

        local fontNames = RUI.Media.BuildFontSort(lsm)
        local filtered  = {}
        for _, name in ipairs(fontNames) do
            if filterText == "" or name:lower():find(filterText, 1, true) then
                filtered[#filtered + 1] = name
            end
        end

        local curVal  = get()
        local n       = #filtered
        local visRows = math.min(n, MENU_MAX_VIS)

        menuFrame:SetHeight(visRows * MENU_ROW_H + SEARCH_H + 8)
        scrollChild:SetSize(rowW, n * MENU_ROW_H)

        if scrollFrame.ScrollBar then
            if n > MENU_MAX_VIS then scrollFrame.ScrollBar:Show()
            else scrollFrame.ScrollBar:Hide() end
        end

        for i, name in ipairs(filtered) do
            local row = CreateFrame("Button", nil, scrollChild)
            row:SetPoint("TOPLEFT", 0, -(i - 1) * MENU_ROW_H)
            row:SetSize(rowW, MENU_ROW_H)

            local hl = row:CreateTexture(nil, "HIGHLIGHT")
            hl:SetAllPoints()
            hl:SetColorTexture(RUI.C.ACCENT.r, RUI.C.ACCENT.g, RUI.C.ACCENT.b, 0.3)

            local fs = row:CreateFontString(nil, "OVERLAY")
            fs:SetPoint("LEFT",  8, 0)
            fs:SetPoint("RIGHT", -8, 0)
            fs:SetJustifyH("LEFT")
            row.Text = fs

            -- Default to standard font, then override with the actual font preview
            fs:SetFontObject(GameFontHighlightSmall)
            local path = RUI.Media.GetFontPath(lsm, name)
            if path then pcall(function() fs:SetFont(path, 12, "") end) end

            fs:SetText(name)

            if name == curVal then
                fs:SetTextColor(RUI.C.ACCENT.r, RUI.C.ACCENT.g, RUI.C.ACCENT.b)
            else
                fs:SetTextColor(RUI.C.TEXT.r, RUI.C.TEXT.g, RUI.C.TEXT.b)
            end

            local fontName = name
            row:SetScript("OnClick", function()
                set(fontName)
                if onSet then onSet(fontName) end
                UpdateButtonText()
                menuFrame:Hide()
            end)

            rows[i] = row
        end
    end

    searchBox:SetScript("OnTextChanged", function(self)
        RebuildRows(self:GetText())
    end)

    -- ── Open / close ──────────────────────────────────────────────────────────

    local function OpenMenu()
        RUI.Draw.CloseOpenMenu()
        menuFrame:ClearAllPoints()
        menuFrame:SetPoint("TOPLEFT",  btn, "BOTTOMLEFT",  0, -2)
        menuFrame:SetPoint("TOPRIGHT", btn, "BOTTOMRIGHT", 0, -2)
        RebuildRows("")
        menuFrame:Show()
        RUI._openMenu = menuFrame

        -- Scroll to currently selected entry (centred in the visible window)
        local fontNames = RUI.Media.BuildFontSort(lsm)
        local curVal    = get()
        for i, name in ipairs(fontNames) do
            if name == curVal then
                local offset = math.max(0, (i - 1) * MENU_ROW_H
                                           - math.floor(MENU_MAX_VIS / 2) * MENU_ROW_H)
                scrollFrame:SetVerticalScroll(offset)
                break
            end
        end
    end

    btn:SetScript("OnClick", function()
        if menuFrame:IsShown() then menuFrame:Hide()
        else OpenMenu() end
    end)

    -- ── Public API ────────────────────────────────────────────────────────────

    local function Refresh()
        UpdateButtonText()
        if menuFrame:IsShown() then RebuildRows(searchBox:GetText()) end
    end
    Refresh()
    return btn, Refresh, lbl
end
