-- lx format
local format = require("core.format")
local pascal_references = require("format.pascal.references")
local quotes = require("core.text.quotes")

local function pascal_single_quote_profile()
	local function escape_pascal(text)
		return (tostring(text or ""):gsub("'", "''")), nil
	end
	local function unescape_pascal(text)
		return (tostring(text or ""):gsub("''", "'")), nil
	end
	return {
		input_multiline = false,
		output_multiline = false,
		delimiters = "'",
		escape = escape_pascal,
		unescape = unescape_pascal,
	}
end

format.register({
	name = "Pascal Source",
	shortname = "Pascal",
	extensions = {
		"pas",
		"pp",
		"dpr", 	-- Delhi project
		"dpk",
		"lpr",
		"inc",	-- Ambiguous
	},
	comment = "//",
	headers = "%{%*%*",
	file_references = pascal_references.new(),
	patterns = {
		{ pattern = "//.-\n", type = "comment" },
		{ pattern = { "%(%*", "%*%)" }, type = "comment" },
		{ pattern = { "{", "}" }, type = "comment" },
		{ pattern = { "'", "'" }, type = "string" },
		{ pattern = "%s*unit%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*interface%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*uses%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*type%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*const%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*private%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*protected%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*public%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*published%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*strict%s+private%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*strict%s+protected%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*strict%s+public%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "%s*strict%s+published%f[%A]", type = "keyword2", line_start = true },
		{ pattern = "[$]%x+", type = "number" },
		{ pattern = "-?%d+[%d%.eE]*", type = "number" },
		{ pattern = "-?%.?%d+", type = "number" },
		{ pattern = "[@%^%+%-=/%*<>:,.;%[%]%(%)]", type = "operator" },
		{ pattern = "[%a_][%w_]*%f[(]", type = "function" },
		{ pattern = "[%a_][%w_]*", type = "symbol" },
	},
	outline_patterns = {
		{ pattern = "%s*unit%f[%A]", line_start = true },
		{ pattern = "%s*interface%f[%A]", line_start = true },
		{ pattern = "%s*implementation%f[%A]", line_start = true },
		{ pattern = "%s*type%f[%A]", line_start = true },
		{ pattern = "%s*class%f[%A]", line_start = true },
		{ pattern = "%s*record%f[%A]", line_start = true },
		{ pattern = "%s*strict%s+private%f[%A]", line_start = true },
		{ pattern = "%s*strict%s+protected%f[%A]", line_start = true },
		{ pattern = "%s*strict%s+public%f[%A]", line_start = true },
		{ pattern = "%s*strict%s+published%f[%A]", line_start = true },
		{ pattern = "%s*private%f[%A]", line_start = true },
		{ pattern = "%s*protected%f[%A]", line_start = true },
		{ pattern = "%s*public%f[%A]", line_start = true },
		{ pattern = "%s*published%f[%A]", line_start = true },
		{ pattern = "%s*function%s+[%a_][%w_%.]*%s*%b()", line_start = true },
		{ pattern = "%s*procedure%s+[%a_][%w_%.]*%s*%b()", line_start = true },
		{ pattern = "%s*constructor%s+[%a_][%w_%.]*%s*%b()", line_start = true },
		{ pattern = "%s*destructor%s+[%a_][%w_%.]*%s*%b()", line_start = true },
	},
	block_comment = {
		block_open = "(*",
		block_close = "*)",
		-- Multiline star-prefixed style so comment cycling behavior matches C-like languages
		block_line_prefix = " * ",
		close_line_prefix = " ",
		open_on_own_line = false,
		close_on_own_line = true,
		-- Strip optional Pascal-style star decoration when uncommenting
		strip_line_prefix = "^%s*%*%s?",
	},
	quotes = {
		primary = "single",
		profiles = {
			single = pascal_single_quote_profile(),
		},
	},
	symbols = {
		["absolute"] = "keyword",
		["and"] = "keyword",
		["array"] = "keyword",
		["as"] = "keyword",
		["asm"] = "keyword",
		["begin"] = "keyword",
		["break"] = "keyword",
		["case"] = "keyword",
		["class"] = "keyword",
		["constructor"] = "keyword",
		["continue"] = "keyword",
		["destructor"] = "keyword",
		["deprecated"] = "keyword",
		["dynamic"] = "keyword",
		["div"] = "keyword",
		["do"] = "keyword",
		["downto"] = "keyword",
		["else"] = "keyword",
		["end"] = "keyword",
		["except"] = "keyword",
		["exports"] = "keyword",
		["file"] = "keyword",
		["finalization"] = "keyword",
		["finally"] = "keyword",
		["for"] = "keyword",
		["function"] = "keyword",
		["goto"] = "keyword",
		["if"] = "keyword",
		["implementation"] = "keyword",
		["in"] = "keyword",
		["inherited"] = "keyword",
		["initialization"] = "keyword",
		["inline"] = "keyword",
		["is"] = "keyword",
		["label"] = "keyword",
		["library"] = "keyword",
		["mod"] = "keyword",
		["nil"] = "literal",
		["not"] = "keyword",
		["object"] = "keyword",
		["of"] = "keyword",
		["or"] = "keyword",
		["overload"] = "keyword",
		["override"] = "keyword",
		["out"] = "keyword",
		["packed"] = "keyword",
		["procedure"] = "keyword",
		["program"] = "keyword",
		["property"] = "keyword",
		["raise"] = "keyword",
		["record"] = "keyword",
		["repeat"] = "keyword",
		["resourcestring"] = "keyword",
		["set"] = "keyword",
		["static"] = "keyword",
		["shl"] = "keyword",
		["shr"] = "keyword",
		["then"] = "keyword",
		["threadvar"] = "keyword",
		["to"] = "keyword",
		["try"] = "keyword",
		["until"] = "keyword",
		["var"] = "keyword",
		["while"] = "keyword",
		["with"] = "keyword",
		["xor"] = "keyword",

		["AnsiString"] = "keyword2",
		["Boolean"] = "keyword2",
		["Byte"] = "keyword2",
		["Cardinal"] = "keyword2",
		["Char"] = "keyword2",
		["Double"] = "keyword2",
		["Extended"] = "keyword2",
		["Integer"] = "keyword2",
		["Int64"] = "keyword2",
		["LongInt"] = "keyword2",
		["Longint"] = "keyword2",
		["NativeInt"] = "keyword2",
		["NativeUInt"] = "keyword2",
		["PChar"] = "keyword2",
		["Pointer"] = "keyword2",
		["Real"] = "keyword2",
		["ShortInt"] = "keyword2",
		["Single"] = "keyword2",
		["SmallInt"] = "keyword2",
		["String"] = "keyword2",
		["UInt64"] = "keyword2",
		["UnicodeString"] = "keyword2",
		["WideChar"] = "keyword2",
		["Word"] = "keyword2",

		["Deprecated"] = "keyword",
		["Dynamic"] = "keyword",
		["Inline"] = "keyword",
		["Overload"] = "keyword",
		["Override"] = "keyword",
		["Static"] = "keyword",

		["False"] = "literal",
		["True"] = "literal",
	},
})
