-- lx-bundle:true

--- Provide a small fixed palette for custom UI drawing
-- Theme authors see a readable tree while prepared Themes use the stable leaf tokens as direct lookup keys
-- @module qui.palette

local colors = require("qui.colors")

local palette = {}
local color_names = {
	"red",
	"orange",
	"yellow",
	"green",
	"blue",
	"purple",
}
local strengths = {
	"strong",
	"soft",
}
local roles = {
	"color",
	"contrast",
}

-- Missing palette colors stay deliberately obvious and readable even when no Theme has loaded
local absence_by_strength = {
	strong = {
		color = colors.red,
		contrast = colors.white,
	},
	soft = {
		color = colors.gray,
		contrast = colors.black,
	},
}

for _, color_name in ipairs(color_names) do
	local color_entry = {}
	palette[color_name] = color_entry

	for _, strength in ipairs(strengths) do
		local strength_entry = {}
		color_entry[strength] = strength_entry

		for _, role in ipairs(roles) do
			local token = table.concat({ "palette", color_name, strength, role }, ".")
			strength_entry[role] = colors.register_token(token, absence_by_strength[strength][role])
		end
	end
end

--- Flatten one readable palette declaration into stable prepared-color keys
-- Partial declarations are valid because shared defaults and absence colors fill omitted leaves
-- @param definition table palette tree from a Theme
-- @return table values
function palette.flatten(definition)
	assert(type(definition) == "table", "qui Theme palette must be a table")
	local values = {}

	for color_name, color_definition in pairs(definition) do
		local color_entry = palette[color_name]
		assert(type(color_name) == "string" and color_entry ~= nil,
			"unknown qui Theme palette color " .. tostring(color_name))
		assert(type(color_definition) == "table",
			"qui Theme palette." .. color_name .. " must be a table")

		for strength, strength_definition in pairs(color_definition) do
			local strength_entry = color_entry[strength]
			assert(type(strength) == "string" and strength_entry ~= nil,
				"unknown qui Theme palette strength " .. color_name .. "." .. tostring(strength))
			assert(type(strength_definition) == "table",
				"qui Theme palette." .. color_name .. "." .. strength .. " must be a table")

			for role, value in pairs(strength_definition) do
				local token = strength_entry[role]
				assert(type(role) == "string" and token ~= nil,
					"unknown qui Theme palette role " ..
					color_name .. "." .. strength .. "." .. tostring(role))
				values[token] = value
			end
		end
	end

	return values
end

return palette
