-- VDS_Components_CanvasScope
-- ============================================================================
-- scopeDropdown -- a WowStyle1DropdownTemplate that picks a curated theme or
-- a user-defined custom palette as the dye source for canvas (what-if mode).
--
-- Menu structure (two-tier; mirrors Blizzard_HousingCatalogFilters.lua pattern):
--   • All Dyes            (radio, clears scope)
--   ──────────────
--   • Themes        ▶     submenu, grid-mode (auto-columns for ~23 items)
--   • Custom Palettes ▶   submenu, grid-mode (auto-columns for user's palettes)
--
-- Selection state reads session.ui.byView.canvas.scope; clicks dispatch
-- CANVAS_SET_SCOPE { value = scope } and let the reducer + BindingEngine
-- re-paint the dropdown via GenerateMenu().

VDS = VDS or {}
local Types = VDS.WidgetTypes

-- Builds the menu description tree. Called every time the dropdown opens
-- AND every time GenerateMenu() is invoked (e.g. when external state changes).
local function buildScopeMenu(_owner, rootDescription)
    local A = VDS.Constants.ACTIONS
    local Selectors = VDS.Selectors

    local function currentScope()
        return VDS.Store:GetState().session.ui.byView.canvas.scope
    end

    -- The selection-text shown on the dropdown button is auto-derived from
    -- the selected radio's text. "All Dyes" radio at top renders as "All Dyes".

    rootDescription:CreateRadio(
        "All Dyes",
        function() return currentScope() == nil end,
        function()
            VDS.Store:Dispatch({ type = A.CANVAS_SET_SCOPE, payload = { value = nil } })
        end
    )
    rootDescription:CreateDivider()

    -- Themes submenu -----------------------------------------------------------
    local themesSubmenu = rootDescription:CreateButton("Themes")
    themesSubmenu:SetGridMode(MenuConstants.VerticalGridDirection)
    -- Themes don't count for the selection-text rollup -- only the leaf radio does.
    themesSubmenu:SetSelectionIgnored()
    local themes = Selectors:Call("canvas.scope.themesList", VDS.Store:GetState(), {})
    for _, t in ipairs(themes) do
        local name = t.name
        themesSubmenu:CreateRadio(
            name,
            function()
                local s = currentScope()
                return s ~= nil and s.kind == "theme" and s.name == name
            end,
            function()
                VDS.Store:Dispatch({
                    type    = A.CANVAS_SET_SCOPE,
                    payload = { value = { kind = "theme", name = name } },
                })
            end
        )
    end

    -- Custom palettes submenu --------------------------------------------------
    local customs = Selectors:Call("canvas.scope.customsList", VDS.Store:GetState(), {})
    if #customs > 0 then
        local customSubmenu = rootDescription:CreateButton("Custom Palettes")
        customSubmenu:SetGridMode(MenuConstants.VerticalGridDirection)
        customSubmenu:SetSelectionIgnored()
        for _, c in ipairs(customs) do
            local name = c.name
            customSubmenu:CreateRadio(
                name,
                function()
                    local s = currentScope()
                    return s ~= nil and s.kind == "custom" and s.name == name
                end,
                function()
                    VDS.Store:Dispatch({
                        type    = A.CANVAS_SET_SCOPE,
                        payload = { value = { kind = "custom", name = name } },
                    })
                end
            )
        end
    end
end

Types:Register("scopeDropdown", {
    build = function(parent, spec)
        -- WowStyle2DropdownTemplate: `common-dropdown-c-button` atlas (darker
        -- metal-plate chrome) + MenuStyle2Mixin popup. Uses
        -- DropdownSelectionTextMixin (NOT DropdownTextMixin) so trigger text
        -- auto-renders from the selected radio -- no manual SetText needed.
        -- Native height 25 (vs Filter's 22).
        local dd = CreateFrame("DropdownButton", nil, parent, "WowStyle2DropdownTemplate")
        dd.resizeToTextMinWidth = spec.width  -- DropdownSelectionTextMixin inherits resizeToText
        dd:SetDefaultText("All Dyes")          -- fallback when no radio is selected
        dd:SetupMenu(buildScopeMenu)
        VDS.TooltipEngine:AttachFromSpec(dd, spec)
        -- Size set by layout engine post-build via spec.width / spec.height.
        return dd
    end,
    -- canvas.scope.label binds here. Push sets the trigger text + regenerates
    -- the menu (so if it's open, the radios re-mark their isSelected state).
    dispatch = {
        fields = { "text" },
        push   = function(widget, values)
            if values.text and widget.SetText then widget:SetText(tostring(values.text)) end
            if widget.GenerateMenu then widget:GenerateMenu() end  -- exception(boundary): GenerateMenu exists once MenuUtil attaches the mixin
        end,
    },
    specFields = { "binding", "width", "height" },
})
