-- lx format
local format = require("core.format")
local quotes = require("core.text.quotes")
local ts_references = require("format.ts.references")

format.register({
	name = "TypeScript Source",
	shortname = "TS",
	author = "liqube",
	extensions = {
		"ts", "tsx", "mts", "cts", "astro"
	},
	comment = "//",

	file_references = ts_references.new(),

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

		-- Strings
		{ pattern = { '"', '"', "\\" }, type = "string" },
		{ pattern = { "'", "'", "\\" }, type = "string" },
		{ pattern = { "`", "`", "\\" }, type = "string" },

		-- Numbers
		{ pattern = "0x[%da-fA-F]+", type = "hex" },
		{ pattern = "0b[01]+", type = "number" },
		{ pattern = "0o[0-7]+", type = "number" },
		{ pattern = "-?%d+[%d%.eE]*", type = "number" },
		{ pattern = "-?%.?%d+", type = "number" },

		-- Operators (no regex literal handling -> '/' is just an operator)
		{ pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" },

		-- TS declarations: highlight keyword + declared name
		{ pattern = "interface%s()[%a_][%w_]*", type = { "keyword", "keyword2" } },
		{ pattern = "type%s()[%a_][%w_]*", type = { "keyword", "keyword2" } },

		-- Functions
		{ pattern = "[%a_][%w_]*%f[(]", type = "function" },

		-- Symbols and identifiers
		{ pattern = "[%a_][%w_]*", type = "symbol" },
	},

	outline_patterns = {
		-- Imports and exports
		{ pattern = "%s*import%s+.-%s+from%s+.-", line_start = true },
		{ pattern = "%s*export%s+%*%s+from%s+.-", line_start = true },
		{ pattern = "%s*export%s+%b{}%s+from%s+.-", line_start = true },
		{ pattern = "%s*export%s+%b{}%s*$", line_start = true },
		{ pattern = "%s*export%s+default%s+.-", line_start = true },

		-- Exported declarations
		{ pattern = "%s*export%s+class%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*export%s+interface%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*export%s+type%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*export%s+enum%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*export%s+namespace%s+[%a_][%w_]*", line_start = true },

		-- Exported functions (incl. generics)
		{ pattern = "%s*export%s+function%s+[%a_][%w_]*%s*%b<>%s*%b()", line_start = true },
		{ pattern = "%s*export%s+function%s+[%a_][%w_]*%s*%b()", line_start = true },

		-- Exported arrow functions (incl. async + generics)
		{ pattern = "%s*export%s+const%s+[%a_][%w_]*%s*=%s*%b<>%s*%b()%s*=>", line_start = true },
		{ pattern = "%s*export%s+const%s+[%a_][%w_]*%s*=%s*async%s*%b<>%s*%b()%s*=>", line_start = true },
		{ pattern = "%s*export%s+const%s+[%a_][%w_]*%s*=%s*%b()%s*=>", line_start = true },
		{ pattern = "%s*export%s+const%s+[%a_][%w_]*%s*=%s*async%s*%b()%s*=>", line_start = true },

		-- Top-level declarations (non-exported)
		{ pattern = "%s*class%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*interface%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*type%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*enum%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*namespace%s+[%a_][%w_]*", line_start = true },

		-- Non-exported functions (incl. generics)
		{ pattern = "%s*function%s+[%a_][%w_]*%s*%b<>%s*%b()", line_start = true },
		{ pattern = "%s*function%s+[%a_][%w_]*%s*%b()", line_start = true },

		-- Common value declarations
--		{ pattern = "%s*const%s+[%a_][%w_]*%s*=", line_start = true },
--		{ pattern = "%s*let%s+[%a_][%w_]*%s*=", line_start = true },

		-- Ambient surface
		{ pattern = "%s*declare%s+module%s+.-", line_start = true },
		{ pattern = "%s*declare%s+namespace%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*declare%s+class%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*declare%s+function%s+[%a_][%w_]*%s*%b()", line_start = true },
		{ pattern = "%s*declare%s+const%s+[%a_][%w_]*", line_start = true },

		-- Decorators (TS/Angular/Nest)
		{ pattern = "%s*@[%a_][%w_]*%s*%b()", line_start = true },
		{ pattern = "%s*@[%a_][%w_]*", line_start = true },

		-- JSX and TSX tags (surface-level components)
		-- Note that this outlines *any* tag
--		{ pattern = "%s*<[%a_][%w_]*", 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?",
	},

	guard_comment = {
		guard_open = { "if (false) {", "if (0) {" },
		guard_close = "}",
		guard_body_prefix = "auto",
		guard_align_to_indent = true,
		allow_nested = true,
	},

	quotes = {
		primary = "double",
		secondary = "single",
		profiles = {
			double = quotes.profile.c_style_double(),
			single = quotes.profile.c_style_single(),
		},
	},

	symbols = {
		-- Variable Declarations
		["const"] = "keyword", -- Block-scoped constant
		["let"] = "keyword", -- Block-scoped variable
		["var"] = "keyword", -- Function-scoped variable

		-- Control Flow
		["break"] = "keyword", -- Exit loop or switch
		["case"] = "keyword", -- Switch case label
		["continue"] = "keyword", -- Skip to next loop iteration
		["default"] = "keyword", -- Switch default case
		["do"] = "keyword", -- Start of do-while loop
		["else"] = "keyword", -- If-else branch
		["for"] = "keyword", -- For loop
		["if"] = "keyword", -- Conditional branch
		["return"] = "keyword", -- Exit function and return value
		["switch"] = "keyword", -- Multi-way branch
		["while"] = "keyword", -- Standard while loop

		-- Loop Helpers
		["of"] = "keyword", -- Used in for...of loops

		-- Error Handling & Debugging
		["try"] = "keyword", -- Start error-handling block
		["catch"] = "keyword", -- Handle exception
		["finally"] = "keyword", -- Always executed block
		["throw"] = "keyword", -- Explicitly throw exception
		["debugger"] = "keyword", -- Invoke debugger/breakpoint

		-- Logic & Operators
		["delete"] = "keyword", -- Remove property from object
		["in"] = "keyword", -- Check property in object
		["instanceof"] = "keyword", -- Type check against constructor
		["new"] = "keyword", -- Instantiate object or class
		["typeof"] = "keyword", -- Evaluate type of operand
		["void"] = "keyword", -- Evaluate expression as undefined

		-- Functions & Async
		["function"] = "keyword", -- Declare a function
		["async"] = "keyword", -- Define asynchronous function
		["await"] = "keyword", -- Wait for promise resolution
		["yield"] = "keyword", -- Generator pause/resume

		-- OOP & Classes
		["class"] = "keyword", -- Define a class
		["extends"] = "keyword", -- Class inheritance
		["super"] = "keyword", -- Reference parent constructor/method
		["static"] = "keyword", -- Class-level method or property
		["get"] = "keyword", -- Getter property defined
		["set"] = "keyword", -- Setter property defined
		["abstract"] = "keyword", -- Abstract class or method
		["override"] = "keyword", -- Override a base class member

		-- Visibility & Modifiers
		["public"] = "keyword", -- Public member (TypeScript)
		["protected"] = "keyword", -- Protected member (TypeScript)
		["private"] = "keyword", -- Private member (TypeScript)
		["readonly"] = "keyword", -- Read-only field or property

		-- Modules
		["import"] = "keyword", -- Import module members
		["export"] = "keyword", -- Export module members
		["from"] = "keyword", -- Specify module source
		["as"] = "keyword", -- Alias in import/export

		-- Type System (TypeScript)
		["type"] = "keyword", -- Type alias declaration
		["interface"] = "keyword", -- Interface declaration
		["implements"] = "keyword", -- Class implements interface(s)
		["enum"] = "keyword", -- Enumeration declaration
		["declare"] = "keyword", -- Ambient declaration
		["namespace"] = "keyword", -- Namespace declaration (TS)
		["module"] = "keyword", -- Module declaration (TS/legacy)
		["keyof"] = "keyword", -- Get keys of a type
		["infer"] = "keyword", -- Infer a type in conditional types
		["is"] = "keyword", -- Type predicate keyword
		["satisfies"] = "keyword", -- Constrain expression type (TS 4.9+)
		["asserts"] = "keyword", -- Assertion signature keyword
		["unknown"] = "keyword", -- Unknown type
		["never"] = "keyword", -- Never type
		["any"] = "keyword", -- Any type

		-- Modern / Contextual
		["target"] = "keyword", -- Used in new.target (ES6)
		["using"] = "keyword", -- Explicit resource management (ES2023+)
		["with"] = "keyword", -- Extends scope chain (deprecated)

		-- Context & Built-ins (keyword2)
		["this"] = "keyword2", -- Current execution context
		["arguments"] = "keyword2", -- Local arguments object in functions
		["Infinity"] = "keyword2", -- Numeric infinity
		["NaN"] = "keyword2", -- Not-a-Number

		-- Literals
		["true"] = "literal", -- Boolean true literal
		["false"] = "literal", -- Boolean false literal
		["null"] = "literal", -- Null literal
		["undefined"] = "literal", -- Undefined value
	},
})
