-- HousingDecorGuide/Core/HDG_RoomShapeAtlas.lua
-- Pure data: room shape identifier → atlas element name, footprint, door anchors.
-- Footprint is in canvas cells (not Blizzard's internal grid units). Default door
-- anchor is the midpoint of each occupied side; renderer uses these as line
-- start/end points and as orb positions for unoccupied doors.

local _, privateDB = ...
local M = {}

-- shape ID → { atlas, cells = {w, h}, doors = {N|E|S|W}, budget = N }
-- Atlas names verified against DevTools/atlas/data/UiTextureAtlasElement.csv.
-- NOTE: Blizzard misspells "Octogon" (Octagon). Atlas names use the misspelling.
-- Budget values pulled from DB2 HouseRoom.WeightCost (12.0.5, 2026-05-02
-- export from wago.tools). Authoritative — matches what
-- C_HousingLayout.GetSpentPlacementBudget() reports in-game.
local SHAPES = {
    closet_xs        = { atlas = "Layout_Closet_XS_Icon",                 cells = {1, 1}, doors = {"N","S"},                budget = 1  },
    square_xs        = { atlas = "Layout_Square_XS_Icon",                 cells = {1, 1}, doors = {"N","E","S","W"},        budget = 2  },
    square_s         = { atlas = "Layout_Square_S_Icon",                  cells = {2, 2}, doors = {"N","E","S","W"},        budget = 5  },
    square_m         = { atlas = "Layout_Square_M_Icon",                  cells = {3, 3}, doors = {"N","E","S","W"},        budget = 12 },
    square_l         = { atlas = "Layout_Square_L_Icon",                  cells = {4, 4}, doors = {"N","E","S","W"},        budget = 20 },
    octagon_s        = { atlas = "Layout_Octogon_S_Icon",                 cells = {2, 2}, doors = {"N","E","S","W"},        budget = 4  },
    octagon_m        = { atlas = "Layout_Octogon_M_Icon",                 cells = {3, 3}, doors = {"N","E","S","W"},        budget = 8  },
    octagon_l        = { atlas = "Layout_Octogon_L_Icon",                 cells = {4, 4}, doors = {"N","E","S","W"},        budget = 16 },
    l_shape          = { atlas = "Layout_L-Shape_S_Icon",                 cells = {2, 2}, doors = {"E","W"},                budget = 3  },
    t_shape          = { atlas = "Layout_T-Shape_S_Icon",                 cells = {2, 2}, doors = {"N","E","W"},            budget = 3  },
    cross_shape      = { atlas = "Layout_Cross_S_Icon",                   cells = {3, 3}, doors = {"N","E","S","W"},        budget = 4  },
    hallway          = { atlas = "Layout_Hallway_S_Icon",                 cells = {2, 1}, doors = {"E","W"},                budget = 3  },
    tall_room        = { atlas = "Layout_TallRoom_S_Icon",                cells = {2, 2}, doors = {"N","E","S","W"},        budget = 6  },  -- "Stairwell Room (Empty)" in DB2
    staircase        = { atlas = "Layout_Staircase_S_Icon",               cells = {2, 2}, doors = {"N","S"},                budget = 7  },
    staircase_mirror = { atlas = "Layout_Staircase_Mirrored_S_Icon",      cells = {2, 2}, doors = {"N","S"},                budget = 7  },
    circle_evening   = { atlas = "Full_Layout_Artisinal_Garden_Evening",  cells = {3, 3}, doors = {"N"},                    budget = 8  },
    circle_daylight  = { atlas = "Full_Layout_Artisinal_Garden_Daylight", cells = {3, 3}, doors = {"N"},                    budget = 8  },
    -- Entry doesn't consume placement budget — it's the structural anchor.
    entry            = { atlas = "Layout_Square_XS_Icon",                 cells = {1, 1}, doors = {"N"},                    budget = 0  },
}

function M.GetBudget(shapeID)
    local s = SHAPES[shapeID]
    return s and s.budget or 0
end

function M.GetShape(shapeID)
    return SHAPES[shapeID]
end

function M.GetAtlas(shapeID)
    local s = SHAPES[shapeID]
    return s and s.atlas
end

function M.GetCells(shapeID)
    local s = SHAPES[shapeID]
    return s and s.cells or { 1, 1 }
end

function M.GetDoors(shapeID)
    local s = SHAPES[shapeID]
    return s and s.doors or {}
end

function M.IsKnown(shapeID)
    return SHAPES[shapeID] ~= nil
end

-- Stable display order for palette UIs. "entry" omitted — it's a marker,
-- not a placeable shape. Order groups by family (Square, Octagon, Specialty,
-- Stairs) per the spec's palette layout.
local PALETTE_ORDER = {
    "closet_xs",
    "square_xs", "square_s", "square_m", "square_l",
    "octagon_s", "octagon_m", "octagon_l",
    "l_shape", "t_shape", "cross_shape",
    "hallway", "tall_room",
    "staircase", "staircase_mirror",
    "circle_evening", "circle_daylight",
}

function M.ListShapes()
    return PALETTE_ORDER
end

-- User-facing label for a shape ID. Derived from the atlas name; strips the
-- "Layout_" prefix and "_Icon" suffix and converts to title case-ish.
local NAME_OVERRIDES = {
    closet_xs        = "Closet",
    square_xs        = "Square XS",
    square_s         = "Square S",
    square_m         = "Square M",
    square_l         = "Square L",
    octagon_s        = "Octagon S",
    octagon_m        = "Octagon M",
    octagon_l        = "Octagon L",
    l_shape          = "L-Shape",
    t_shape          = "T-Shape",
    cross_shape      = "Cross",
    hallway          = "Hallway",
    tall_room        = "Tall",
    staircase        = "Stairs",
    staircase_mirror = "Stairs (rev)",
    circle_evening   = "Garden (Eve)",
    circle_daylight  = "Garden (Day)",
}

function M.GetLabel(shapeID)
    return NAME_OVERRIDES[shapeID] or shapeID
end

if privateDB then privateDB.HDG_RoomShapeAtlas = M end
return M
