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

-- ─── Builder — y-cursor layout engine for options panels and dialogs ──────────
-- Superset of AddonOptionsPanel-1.0. Drop-in replacement: swap the library ref
-- and change AOP:New() → RUI:Builder().
--
-- Usage (Blizzard settings panel):
--   local b = RUI:Builder(panel, lsm)
--   b:Header("Section Title")
--   b:BeginSection("Box Title"); ... controls ...; b:EndSection()
--   b:MakeSlider(...)
--   b:MakeDropdown(...)
--   b:FinalizeOnShow()
--   Settings.RegisterAddOnCategory(Settings.RegisterCanvasLayoutCategory(panel, "Name"))
--
-- Two-column layout:
--   local topY = b:GetY()
--   b:MakeDropdown("Left", RUI.PAD, RUI.DD_HALF, ...)
--   local leftY = b:GetY()
--   b:SetY(topY)
--   b:MakeSlider("Right", RUI.COL2_X, RUI.SLD_HALF, ...)
--   b:SetY(math.min(leftY, b:GetY()))   -- advance past the deeper column

local SECTION_MARGIN  = 8
local SECTION_PAD_TOP = 6
local SECTION_PAD_BOT = 10
local SECTION_GAP     = 12
local SECTION_SEP     = 6

local Builder = {}
Builder.__index = Builder

function RUI:Builder(panel, lsm)
    return setmetatable({
        panel         = panel,
        lsm           = lsm,
        y             = -RUI.PAD,
        allRefreshFns = {},
        _firstSection = true,
    }, Builder)
end

function Builder:GetY() return self.y end
function Builder:SetY(y) self.y = y end

-- Advances the y cursor by px without creating any widget.
function Builder:Spacer(px)
    self.y = self.y - px
end

-- Registers OnShow and OnRefresh (called by Blizzard Settings canvas) to refresh all controls.
function Builder:FinalizeOnShow()
    local fns = self.allRefreshFns
    local function RefreshAll()
        for _, fn in ipairs(fns) do fn() end
    end
    self.panel:SetScript("OnShow", RefreshAll)
    self.panel.OnRefresh = RefreshAll
end

-- Section header text (22px). 14px gap inserted before all but the first.
function Builder:Header(title)
    if not self._firstSection then self.y = self.y - 14 end
    self._firstSection = false
    local fs = RUI.Draw.MakeHeader(self.panel)
    fs:SetTextColor(RUI.C.ACCENT.r, RUI.C.ACCENT.g, RUI.C.ACCENT.b)
    fs:SetPoint("TOPLEFT", self.panel, "TOPLEFT", RUI.PAD, self.y)
    fs:SetText(title)
    self.y = self.y - RUI.HEADER_H
end

-- 1px horizontal rule across the panel (8px vertical advance).
function Builder:MakeSeparator(x, width)
    RUI.Widget.Separator(self.panel, x, self.y, width)
    self.y = self.y - 8
end

local SECTION_TITLE_H = 24  -- height of title header row inside the box

-- Begins a bordered section box. Title is inside the box at the top (DandersFrames style).
-- Controls placed between Begin and End are indented below the title row.
function Builder:BeginSection(title)
    if not self._firstSection then self.y = self.y - SECTION_GAP end
    self._firstSection = false

    local panel = self.panel
    local m  = SECTION_MARGIN
    local bc = RUI.C.BORDER

    local topY = self.y  -- box top; title lives inside from here

    -- Title text: 5px from box top, 8px from left edge
    local fs = RUI.Draw.MakeHeader(panel)
    fs:SetTextColor(RUI.C.ACCENT.r, RUI.C.ACCENT.g, RUI.C.ACCENT.b)
    fs:SetPoint("TOPLEFT", panel, "TOPLEFT", m + 8, topY - 5)
    fs:SetText(title)

    -- Advance past title row, then inset before first widget
    self.y = self.y - SECTION_TITLE_H - SECTION_PAD_TOP

    local bg = panel:CreateTexture(nil, "BACKGROUND", nil, -8)
    local bt = panel:CreateTexture(nil, "BACKGROUND", nil, -7)
    local bb = panel:CreateTexture(nil, "BACKGROUND", nil, -7)
    local bl = panel:CreateTexture(nil, "BACKGROUND", nil, -7)
    local br = panel:CreateTexture(nil, "BACKGROUND", nil, -7)
    -- DF CreateCollapsibleSection: C_PANEL at 0.8, C_BORDER at 0.5
    bg:SetColorTexture(RUI.C.PANEL.r, RUI.C.PANEL.g, RUI.C.PANEL.b, 0.8)
    for _, t in ipairs({bt, bb, bl, br}) do t:SetColorTexture(bc.r, bc.g, bc.b, 0.5) end

    self._section = {topY=topY, bg=bg, bt=bt, bb=bb, bl=bl, br=br}
end

-- Closes the section box opened by BeginSection.
function Builder:EndSection()
    local s = self._section
    if not s then return end
    self._section = nil

    local panel = self.panel
    local topY  = s.topY
    local botY  = self.y - SECTION_PAD_BOT
    local m     = SECTION_MARGIN

    s.bg:SetPoint("TOPLEFT",     panel, "TOPLEFT",  m,  topY)
    s.bg:SetPoint("BOTTOMRIGHT", panel, "TOPRIGHT", -m, botY)

    s.bt:SetPoint("TOPLEFT",  panel, "TOPLEFT",  m,  topY); s.bt:SetPoint("TOPRIGHT",    panel, "TOPRIGHT",  -m, topY); s.bt:SetHeight(1)
    s.bb:SetPoint("BOTTOMLEFT", panel, "TOPLEFT",  m,  botY); s.bb:SetPoint("BOTTOMRIGHT", panel, "TOPRIGHT",  -m, botY); s.bb:SetHeight(1)
    s.bl:SetPoint("TOPLEFT",  panel, "TOPLEFT",  m,  topY); s.bl:SetPoint("BOTTOMLEFT",  panel, "TOPLEFT",   m,  botY); s.bl:SetWidth(1)
    s.br:SetPoint("TOPRIGHT", panel, "TOPRIGHT", -m, topY); s.br:SetPoint("BOTTOMRIGHT", panel, "TOPRIGHT",  -m, botY); s.br:SetWidth(1)

    self.y = botY
end

function Builder:MakeSlider(labelText, x, sliderW, minVal, maxVal, stepVal, get, set)
    local sld, ref = RUI.Widget.Slider(self.panel, labelText, x, self.y, sliderW, minVal, maxVal, stepVal, get, set)
    self.y = self.y - RUI.LABEL_H - RUI.SLIDER_H - 12 - RUI.CONTROL_GAP
    tinsert(self.allRefreshFns, ref)
    return sld, ref
end

function Builder:MakeDropdown(labelText, x, ddWidth, getEntries, get, set, onSet, ddName)
    local dd, ref, lbl = RUI.Widget.Dropdown(self.panel, labelText, x, self.y, ddWidth, getEntries, get, set, onSet, ddName)
    self.y = self.y - RUI.LABEL_H - RUI.DD_H - RUI.CONTROL_GAP
    tinsert(self.allRefreshFns, ref)
    return dd, ref, lbl
end

function Builder:MakeSoundDropdown(labelText, x, ddWidth, get, set, ddName)
    local dd, ref, lbl = RUI.Widget.SoundDropdown(self.panel, labelText, x, self.y, ddWidth, get, set, self.lsm, ddName)
    self.y = self.y - RUI.LABEL_H - RUI.DD_H - RUI.CONTROL_GAP
    tinsert(self.allRefreshFns, ref)
    return dd, ref, lbl
end

function Builder:MakeFontDropdown(labelText, x, ddWidth, get, set, onSet, ddName)
    local dd, ref, lbl = RUI.Widget.FontDropdown(self.panel, labelText, x, self.y, ddWidth, get, set, self.lsm, onSet, ddName)
    self.y = self.y - RUI.LABEL_H - RUI.DD_H - RUI.CONTROL_GAP
    tinsert(self.allRefreshFns, ref)
    return dd, ref, lbl
end

function Builder:MakeColorButton(labelText, x, width, get_rgba, set_rgba, hasAlpha)
    local btn, ref = RUI.Widget.ColorButton(self.panel, labelText, x, self.y, width, get_rgba, set_rgba, hasAlpha)
    self.y = self.y - RUI.COLOR_H - RUI.CONTROL_GAP  -- 24+4=28px (no separate label row)
    tinsert(self.allRefreshFns, ref)
    return btn, ref
end

function Builder:MakeInput(labelText, x, width, get, set)
    local eb, ref, lbl = RUI.Widget.Input(self.panel, labelText, x, self.y, width, get, set)
    self.y = self.y - RUI.LABEL_H - RUI.INPUT_H - RUI.CONTROL_GAP
    tinsert(self.allRefreshFns, ref)
    return eb, ref, lbl
end

function Builder:MakeTextInput(labelText, x, width, get, set, maxLetters)
    local eb, ref, lbl = RUI.Widget.TextInput(self.panel, labelText, x, self.y, width, get, set, maxLetters)
    self.y = self.y - RUI.LABEL_H - RUI.INPUT_H - RUI.CONTROL_GAP
    tinsert(self.allRefreshFns, ref)
    return eb, ref, lbl
end

function Builder:MakeNumberInput(labelText, x, width, get, set)
    local eb, ref = RUI.Widget.NumberInput(self.panel, labelText, x, self.y, width, get, set)
    self.y = self.y - RUI.LABEL_H - RUI.INPUT_H - RUI.CONTROL_GAP
    tinsert(self.allRefreshFns, ref)
    return eb, ref
end

function Builder:MakeCheckbox(labelText, get, set)
    local wrapper, ref = RUI.Widget.Checkbox(self.panel, labelText, get, set)
    wrapper:SetPoint("TOPLEFT", self.panel, "TOPLEFT", RUI.PAD, self.y)
    self.y = self.y - RUI.CHECK_H - RUI.CONTROL_GAP
    tinsert(self.allRefreshFns, ref)
    return wrapper, ref
end

function Builder:MakeButton(labelText, x, width, onClick)
    local btn = RUI.Widget.Button(self.panel, labelText, width, RUI.BTN_H, onClick)
    btn:SetPoint("TOPLEFT", self.panel, "TOPLEFT", x, self.y)
    self.y = self.y - RUI.BTN_H - RUI.CONTROL_GAP
    return btn
end

function Builder:MakeIconButton(iconPath, labelText, x, width, onClick)
    local btn = RUI.Widget.IconButton(self.panel, iconPath, labelText, width, RUI.BTN_H, onClick)
    btn:SetPoint("TOPLEFT", self.panel, "TOPLEFT", x, self.y)
    self.y = self.y - RUI.BTN_H - RUI.CONTROL_GAP
    return btn
end

function Builder:MakeToggleButton(labelText, x, width, onChange, iconName)
    local btn = RUI.Widget.ToggleButton(self.panel, labelText, width, RUI.BTN_H, onChange, iconName)
    btn:SetPoint("TOPLEFT", self.panel, "TOPLEFT", x, self.y)
    self.y = self.y - RUI.BTN_H - RUI.CONTROL_GAP
    return btn
end

function Builder:MakeTabGroup(options, x, totalWidth, height, onChange)
    local tg = RUI.Widget.TabGroup(self.panel, options, totalWidth, height or RUI.BTN_H, onChange)
    tg:SetPoint("TOPLEFT", self.panel, "TOPLEFT", x, self.y)
    self.y = self.y - (height or RUI.BTN_H) - RUI.CONTROL_GAP
    return tg
end
