-- lx format
local format = require("core.format")
local javascript_references = require("format.js.references")
local quotes = require("core.text.quotes")

format.register({
	name = "JavaScript Source",
	shortname = "JS",
	author = "liqube",
	extensions = {
		"js",
		"mjs",
	},
	comment = "//",

	file_references = javascript_references.new({ ".js", ".mjs", ".cjs", ".jsx", ".json" }),

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

		-- Regex literals at the beginning of an expression must win before their quotes become strings
		-- Pattern breakdown: slash-delimited single-line body followed by optional JavaScript flags
		{ pattern = "/[^\n]-/[dgimsuvy]*", type = "string", line_prefix = "%s*" },
		{ pattern = "/[^\n]-/[dgimsuvy]*", type = "string", preceded_by = "[=(:,!&|?{%[]%s*" },

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

		{ pattern = "0x[%da-fA-F]+", type = "hex" },
		{ pattern = "-?%d+[%d%.eE]*", type = "number" },
		{ pattern = "-?%.?%d+", type = "number" },
		{ pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" },

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

	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

		-- Logic and 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 and Async
		["async"] = "keyword", -- Define asynchronous function
		["await"] = "keyword", -- Wait for promise resolution
		["function"] = "keyword", -- Declare a function
		["yield"] = "keyword", -- Generator pause/resume

		-- OOP and Classes
		["class"] = "keyword", -- Define a class
		["extends"] = "keyword", -- Class inheritance
		["get"] = "keyword", -- Getter property defined
		["set"] = "keyword", -- Setter property defined
		["static"] = "keyword", -- Class-level method or property
		["super"] = "keyword", -- Reference parent constructor/method
		["private"] = "keyword", -- Reserved for future/class use
		["protected"] = "keyword", -- Reserved for future use
		["public"] = "keyword", -- Reserved for future use

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

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

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

		-- Reeserved
		["enum"] = "keyword",
		["implements"] = "keyword",
		["interface"] = "keyword",
		["package"] = "keyword",

		-- Object and Context
		["arguments"] = "keyword2", -- Local object in functions
		["this"] = "keyword2", -- Current execution context

		--  Math
		["Infinity"] = "keyword2", -- Numeric infinity
		["NaN"] = "keyword2", -- Not-a-Number

		-- Literals
		["false"] = "literal",
		["null"] = "literal",
		["true"] = "literal",
		["undefined"] = "literal",
	},
})
