-- DopingControl ui/cellsheet.lua
--
-- The matrix draws one small box per cell: a solid background with a 1px
-- border whose color carries the state. Done with SetBackdrop that costs NINE
-- texture regions per cell (measured in the client: bare frame 0, backdrop
-- with bgFile only 1, backdrop with edgeFile 9). At 805 cells that is ~7200
-- regions of pure decoration.
--
-- Instead every box is baked into one sheet and a cell owns a single texture
-- region that picks its box with SetTexCoord. The border is part of the image,
-- so the result is pixel-identical -- the sheet is generated from the same
-- DC.COLORS palette by tools/gen-cellsheet.js.
--
-- Pure Lua on purpose: no WoW API at file scope, so the offline tests can
-- dofile it under lua50.exe.

DC_Cells = {}

DC_Cells.SHEET = {
    path   = "Interface\\AddOns\\DopingControl\\textures\\cells",
    size   = 256,   -- power of two, mandatory: a 12x12 TGA fails silently
    tileW  = 64,    -- holds the widest sprite (34) with room to spare
    tileH  = 32,    -- holds CELL_H (23)
    perRow = 4,     -- 256 / 64
}

-- Cell height never varies; only the width does (trinket columns are 34).
DC_Cells.CELL_H  = 23
DC_Cells.WIDTHS  = { 30, 34 }

-- Every (background, border) pair a CELL can take, in sheet order. Borders
-- given as a number are DC.QUALITY indices, everything else is a DC.COLORS
-- key. Order is the wire format of the sheet: appending is safe, reordering
-- means regenerating the TGA.
DC_Cells.VARIANTS = {
    { name = "HAS",          bg = "hatBg",   border = "hatBorder"   },
    { name = "MISSING",      bg = "fehltBg", border = "fehltBorder" },
    { name = "UNKNOWN",      bg = "unbekBg", border = "unbekBorder" },
    { name = "SKIP",         bg = "skip",    border = "skipBorder"  },
    { name = "NEUTRAL",      bg = "theadBg", border = "line"        },
    { name = "ITEM_HAS",     bg = "theadBg", border = "hatBorder"   },
    { name = "ITEM_MISSING", bg = "theadBg", border = "fehltBorder" },
    { name = "Q_RARE",       bg = "theadBg", border = "rareBorder"  },
    { name = "Q_EPIC",       bg = "theadBg", border = "epicBorder"  },
    { name = "Q_0",          bg = "theadBg", border = 0 },
    { name = "Q_1",          bg = "theadBg", border = 1 },
    { name = "Q_2",          bg = "theadBg", border = 2 },
    { name = "Q_5",          bg = "theadBg", border = 5 },
    { name = "Q_6",          bg = "theadBg", border = 6 },
}

DC_Cells.INDEX = {}
for i = 1, table.getn(DC_Cells.VARIANTS) do
    DC_Cells.INDEX[DC_Cells.VARIANTS[i].name] = i
end

-- Tile slot of a variant/width pair: each variant owns two consecutive tiles,
-- one per width, in DC_Cells.WIDTHS order.
local function slotOf(name, w)
    local vi = DC_Cells.INDEX[name]
    if not vi then
        return nil
    end
    for k = 1, table.getn(DC_Cells.WIDTHS) do
        if DC_Cells.WIDTHS[k] == w then
            return (vi - 1) * table.getn(DC_Cells.WIDTHS) + (k - 1)
        end
    end
    return nil
end
DC_Cells.SlotOf = slotOf

-- SetTexCoord arguments for one box. Returns four numbers or nil -- nil so a
-- typo shows up as a missing box instead of silently sampling tile 0.
function DC_Cells.Coords(name, w)
    local slot = slotOf(name, w)
    if not slot then
        return nil
    end
    local S = DC_Cells.SHEET
    local col = math.mod(slot, S.perRow)
    local row = math.floor(slot / S.perRow)
    local x0  = col * S.tileW
    local y0  = row * S.tileH
    return x0 / S.size,
           (x0 + w) / S.size,
           y0 / S.size,
           (y0 + DC_Cells.CELL_H) / S.size
end

-- State + slot kind + item quality -> variant name. Mirrors exactly what the
-- old SetBackdropG call sites in ui/matrix.lua chose -- which, for a nil
-- quality, differed BY KIND (see ui/matrix.lua's M.PaintItemTile, old lines
-- 1965-1990, confirmed at tools/luatests/test_cellsheet.lua):
--   * trinket: M.qualityColors(item.quality) ran unconditionally, and for
--     quality == nil that resolves to DC.QUALITY[1] (common/white) via the
--     `q or 1` fallback -- state-INDEPENDENT.
--   * ench: quality == nil skipped M.qualityColors and fell back to
--     C.hatBorder/C.fehltBorder/C.line BY STATE -- exactly
--     ITEM_HAS/ITEM_MISSING/NEUTRAL.
-- So trinket's nil-quality case must NOT share ench's state-based fallback.
function DC_Cells.VariantFor(state, kind, quality)
    if kind == "ench" or kind == "trinket" then
        if quality == 3 then return "Q_RARE" end
        if quality == 4 then return "Q_EPIC" end
        if quality ~= nil then return "Q_" .. quality end
        if kind == "trinket" then
            return "Q_1"
        end
        if state == "HAS" then return "ITEM_HAS" end
        if state == "MISSING" then return "ITEM_MISSING" end
        return "NEUTRAL"
    end
    if state == "HAS" then return "HAS" end
    if state == "MISSING" then return "MISSING" end
    if state == "UNKNOWN" then return "UNKNOWN" end
    return "SKIP"
end
