-- lx format
local format = require("core.format")
local css_references = require("format.css.references")
local vocabulary = require("format.css.vocabulary")

format.register({
	name = "Cascading Style Sheet",
	shortname = "CSS",
	extensions = { "css" },

	file_references = css_references.new(),

	patterns = {
		-- Escaped dot (legacy / keep as-is)
		{ pattern = "\\.", type = "normal" },

		-- Block comment /* ... */
		{ pattern = { "/%*", "%*/" }, type = "comment" },

		-- Double-quoted string "..."
		{ pattern = { '"', '"', "\\\\" }, type = "string" },

		-- Single-quoted string '...'
		{ pattern = { "'", "'", "\\\\" }, type = "string" },

		-- !important (specificity override)
		{ pattern = "%s+!important", type = "label" },

		-- Unicode range U+0000-00FF form
		{ pattern = "U%+%x%x%x%x%-%x%x%x%x", type = "hex" },

		-- Unicode range U+00FF form
		{ pattern = "U%+%x%x%x%x", type = "hex" },

		-- Custom property definition name before colon: --foo:
		{ pattern = "%-%-[^%s:;,%)}%]]+%s*%f[:]", type = "variable" },

		--- Direction keywords used as values inside declarations
		-- left: 30px;
		-- left: auto;
		-- transition: left 200ms ease;
		{
			pattern = "%f[%a_]left%f[^%w_-]",
			type = "keyword2",
			preceded_by = ":%s*[^;\n}]*",
		},
		{
			pattern = "%f[%a_]right%f[^%w_-]",
			type = "keyword2",
			preceded_by = ":%s*[^;\n}]*",
		},
		{
			pattern = "%f[%a_]top%f[^%w_-]",
			type = "keyword2",
			preceded_by = ":%s*[^;\n}]*",
		},
		{
			pattern = "%f[%a_]bottom%f[^%w_-]",
			type = "keyword2",
			preceded_by = ":%s*[^;\n}]*",
		},

		--- Selectors (CSS + QSS) — put these BEFORE colors and properties

		-- ID selector token: #fader32
		-- (Must come before hex colors so #fade inside #fader32 doesn't get stolen.)
		{ pattern = "#[%a_][%w_-]*", type = "keyword2" },

		-- QSS subcontrol: ::handle
		{ pattern = "::[%a_][%w_-]*", type = "keyword2" },

		-- QSS pseudo-state: :vertical, :hover, :pressed, etc.
		-- NOTE: kept broad; declaration properties are constrained separately.
		{ pattern = ":[%a_][%w_-]*", type = "keyword2" },

		-- Class selector token like .button (keep as-is)
		{ pattern = "%.[%a][%w_-]*", type = "keyword2" },

		-- At-rule token like @media (keep as-is)
		{ pattern = "@[%a][%w_-]*", type = "keyword2" },

		--- Colors

		-- Hex colors: #rgb, #rgba, #rrggbb, #rrggbbaa (strict)
		-- Use %f[^%x] so we don't partially match things like #fade inside #fader32.
		{ pattern = "#%x%x%x%x%x%x%x%x%f[^%x]", type = "string" }, -- 8
		{ pattern = "#%x%x%x%x%x%x%f[^%x]", type = "string" },     -- 6
		{ pattern = "#%x%x%x%x%f[^%x]", type = "string" },         -- 4
		{ pattern = "#%x%x%x%f[^%x]", type = "string" },           -- 3

		--- Declaration property names (constrained to declaration context)

		-- Standard property name before colon: color:
		-- Constrain to declaration context: after '{' or ';' (optionally with whitespace).
		{
			pattern = "[%a_][%w_-]*%s*%f[:]",
			type = "keyword",
			preceded_by = "[{;]%s*",
		},

		-- Custom property reference anywhere: var(--foo) or --foo used in values
		{ pattern = "%-%-[^%s:;,%)}%]]+", type = "variable" },

		--- Units (capture-colored)
		-- NOTE: keep BEFORE plain number rules.
		{
			-- number + unit (unit recolored via post_symbols)
			pattern = "(-?%d+[%d%.]*)(%%?[%a]+)",
			type = { "number", "symbol" },
			post_symbols = "unit_symbols",
		},

		-- Absolute length units
--		{ pattern = "(-?%d+[%d%.]*)(p[xtc])", type = { "number", "operator" } }, -- px pt pc
--		{ pattern = "(-?%d+[%d%.]*)([cm]m)", type = { "number", "operator" } },  -- cm mm
--		{ pattern = "(-?%d+[%d%.]*)(in)", type = { "number", "operator" } },     -- in

		-- Relative length units
--		{ pattern = "(-?%d+[%d%.]*)(r?em)", type = { "number", "operator" } },   -- em rem
--		{ pattern = "(-?%d+[%d%.]*)(ex)", type = { "number", "operator" } },     -- ex
--		{ pattern = "(-?%d+[%d%.]*)(ch)", type = { "number", "operator" } },     -- ch

		-- Viewport units
--		{ pattern = "(-?%d+[%d%.]*)(v[wh])", type = { "number", "operator" } },       -- vw vh
--		{ pattern = "(-?%d+[%d%.]*)(vmin)", type = { "number", "operator" } },        -- vmin
--		{ pattern = "(-?%d+[%d%.]*)(vmax)", type = { "number", "operator" } },        -- vmax

		-- Time units
--		{ pattern = "(-?%d+[%d%.]*)(ms)", type = { "number", "operator" } },          -- ms
--		{ pattern = "(-?%d+[%d%.]*)(s)", type = { "number", "operator" } },           -- s

		-- Angle units
--		{ pattern = "(-?%d+[%d%.]*)(deg)", type = { "number", "operator" } },         -- deg
--		{ pattern = "(-?%d+[%d%.]*)(rad)", type = { "number", "operator" } },         -- rad
--		{ pattern = "(-?%d+[%d%.]*)(grad)", type = { "number", "operator" } },        -- grad
--		{ pattern = "(-?%d+[%d%.]*)(turn)", type = { "number", "operator" } },        -- turn

		-- Percentage
--		{ pattern = "(-?%d+[%d%.]*)(%%)", type = { "number", "operator" } },

		--- Numbers

		-- Negative number like -12 or -12.5 (safer than -?%d... for custom props)
		{ pattern = "%-%f[%d]%d+[%d%.]*", type = "number" },

		-- Positive number like 12 or 12.5 (safer split)
		{ pattern = "%d+[%d%.]*", type = "number" },

		--- Functions and identifiers

		-- CSS built-in var( ... ) function call
		{ pattern = "var%s*%f[(]", type = "function" },

		-- Vendor-prefixed function call: -webkit-linear-gradient(
		-- (Leading '-' but NOT '--' because next char must be alpha/_)
		{ pattern = "%-%f[%a_][%w_-]*%s*%f[(]", type = "constant" },

		-- Vendor-prefixed identifier used as a value: -khtml-text, -ms-grid, -moz-initial, etc.
		-- (Leading '-' but NOT '--' because next char must be alpha/_)
		{ pattern = "%-%f[%a_][%w_-]*", type = "constant" },

		-- Generic identifier (fallback) — allow hyphens (inline-block, space-between, etc.)
		{ pattern = "[%a_][%w_-]*", type = "symbol" },

		-- Punctuation

		-- Braces and colon punctuation
		{ pattern = "[{}:]", type = "operator" },
	},

	outline_patterns = {
		{ pattern = "%s*[^@%s][^\n{}]-{%s*$", line_start = true },
		{ pattern = "%s*@[^{\n]-{%s*$", line_start = true },
	},

	block_comment = {
		block_open = "/*",
		block_close = "*/",
		block_line_prefix = " * ",
		close_line_prefix = " ",
		open_on_own_line = false,
		close_on_own_line = true,
		strip_line_prefix = "^%s*%*%s?",
		allow_nested = false,
	},

	guard_comment = {
		guard_open = {
			"@media not all {",
			"@media (width: 0px) and (width: 1px) {",
		},
		guard_close = "}",
		guard_align_to_indent = true,
		allow_nested = true,
	},

	symbols = vocabulary,

	unit_symbols = {
		-- absolute lengths
		["px"] = "unit",
		["pt"] = "unit",
		["pc"] = "unit",
		["cm"] = "unit",
		["mm"] = "unit",
		["in"] = "unit",

		-- relative lengths
		["em"] = "unit",
		["rem"] = "unit",
		["ex"] = "unit",
		["ch"] = "unit",

		-- viewport
		["vw"] = "unit",
		["vh"] = "unit",
		["vmin"] = "unit",
		["vmax"] = "unit",

		-- time
		["ms"] = "unit",
		["s"] = "unit",

		-- angles
		["deg"] = "unit",
		["rad"] = "unit",
		["grad"] = "unit",
		["turn"] = "unit",
	},

})
