-- lx syntax
local syntax = require("core.syntax")
local patterns = require("core.syntax.patterns")
local quotes = require("core.quotes")

syntax.add({
	name = "MoonScript",
	shortname = "Moon",
	author = "liqube",
	extensions = { "moon" },
	comment = "--",

	headers = {
		"^#!.*[ /]moon$",
		"^#!.*[ /]moonscript$",
	},

	line_patterns = {
		-- Function assignment with paren args
		{
			-- Split the head from the operator, then mark the consume boundary after the operator
			pattern = "%s*([%a_][%w_]*)()%s*=%s*%b()%s*[=-]>()",
			type = { "function", "operator" },
			consume_to = 2,
		},

		-- Function assignment without paren args
		{
			-- Split the head from the operator, then mark the consume boundary after the operator
			pattern = "%s*([%a_][%w_]*)()%s*=%s*[=-]>()",
			type = { "function", "operator" },
			consume_to = 2,
		},

		-- Method head with paren args
		{
			-- Split the head from the operator, then mark the consume boundary after the operator
			pattern = "%s*([%a_][%w_]*)()%s*:%s*%b()%s*[=-]>()",
			type = { "function", "operator" },
			consume_to = 2,
		},

		-- Method head without paren args
		{
			-- Split the head from the operator, then mark the consume boundary after the operator
			pattern = "%s*([%a_][%w_]*)()%s*:%s*[=-]>()",
			type = { "function", "operator" },
			consume_to = 2,
		},

		-- Self method head with paren args
		{
			-- Split the head from the operator, then mark the consume boundary after the operator
			pattern = "%s*(@[%a_][%w_]*)()%s*:%s*%b()%s*[=-]>()",
			type = { "function", "operator" },
			consume_to = 2,
		},

		-- Self method head without paren args
		{
			-- Split the head from the operator, then mark the consume boundary after the operator
			pattern = "%s*(@[%a_][%w_]*)()%s*:%s*[=-]>()",
			type = { "function", "operator" },
			consume_to = 2,
		},

		-- Bare function literal with paren args
		{
			-- Split the head from the operator, then mark the consume boundary after the operator
			pattern = "%s*(%b())()%s*[=-]>()",
			type = { "function", "operator" },
			consume_to = 2,
		},

--		-- Plain assignment head
--		{
--			pattern = "%s*([%a_][%w_]*)()%s*=()",
--			type = { "variable", "operator" },
--			not_followed_by = "[=-]>",
--			consume_to = 2,
--		},

		-- Object key at line start
		{
			-- Split the key from the operator, then mark the consume boundary after the operator
			pattern = "%s*([%a_][%w_]*)()%s*:%s*()",
			type = { "symbol", "operator" },
			not_followed_by = "[=-]>",
			consume_to = 2,
		},
	},

	patterns = {
		patterns.shebang_line(),

		-- Block comments
		{ pattern = { "%-%-%[%[", "%]%]" }, type = "comment" },

		-- Line comments
		{ pattern = "%-%-.-\n", type = "comment" },

		-- Long strings
		{ pattern = { "%[%[", "%]%]" }, type = "string" },

		-- Quoted strings
		{ pattern = { '"', '"', "\\" }, type = "string" },
		{ pattern = { "'", "'", "\\" }, type = "string" },

		-- Class variable shorthand
		{ pattern = "@@[%a_][%w_]*", type = "keyword2" },

		-- Instance variable shorthand
		{ pattern = "@[%a_][%w_]*", type = "keyword2" },

		-- Self call shorthand
		{ pattern = "\\[%a_][%w_]*", type = "function" },

		-- Colon shorthand key
		{ pattern = ":[%a_][%w_]*", type = "symbol" },

		-- Function calls with parens
		{ pattern = "[%a_][%w_]*%f[(]", type = "function" },

		-- Dotted access
		{ pattern = "%.[%a_][%w_]*", type = "symbol" },

		-- Hex numbers
		{ pattern = "0[xX][%da-fA-F]+", type = "hex" },

		-- Decimal numbers with fraction
		{ pattern = "%d+%.%d+([eE][%+%-]?%d+)?", type = "number" },

		-- Decimal numbers with exponent
		{ pattern = "%d+[eE][%+%-]?%d+", type = "number" },

		-- Leading dot fraction
		{ pattern = "%.%d+([eE][%+%-]?%d+)?", type = "number" },

		-- Integers
		{ pattern = "%d+", type = "number" },

		-- Multi character operators
		{ pattern = "%.%.%.", type = "operator" },
		{ pattern = "::", type = "operator" },
		{ pattern = "[<!=>]=", type = "operator" },
		{ pattern = "[%+%-*/%%%^%.]=", type = "operator" },
		{ pattern = "%-%>", type = "operator" },
		{ pattern = "=>", type = "operator" },

		-- Single character operators and punctuation
		{ pattern = "[%+%-=/%*%^%%<>#~:,;%.%?%(%)%[%]{}!]", type = "operator" },

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

	outline_patterns = {
		-- Class declaration
		{ pattern = "%s*class%s+[%a_][%w_]*", line_start = true },

		-- Exported class declaration
		{ pattern = "%s*export%s+class%s+[%a_][%w_]*", line_start = true },

		-- Function assignment with paren args
		{ pattern = "%s*[%a_][%w_]*%s*=%s*%b()%s*[=-]>", line_start = true },

		-- Function assignment without paren args
		{ pattern = "%s*[%a_][%w_]*%s*=%s*[=-]>", line_start = true },

		-- Method head with paren args
		{ pattern = "%s*[%a_][%w_]*%s*:%s*%b()%s*[=-]>", line_start = true },

		-- Method head without paren args
		{ pattern = "%s*[%a_][%w_]*%s*:%s*[=-]>", line_start = true },

		-- Self method head with paren args
		{ pattern = "%s*@[%a_][%w_]*%s*:%s*%b()%s*[=-]>", line_start = true },

		-- Self method head without paren args
		{ pattern = "%s*@[%a_][%w_]*%s*:%s*[=-]>", line_start = true },

		-- Bare function literal with paren args
		{ pattern = "%s*%b()%s*[=-]>", line_start = true },
	},

	block_comment = {
		block_open = "--[[",
		block_close = "]]",
		block_line_prefix = "",
		close_line_prefix = "",
		open_on_own_line = true,
		close_on_own_line = true,
		allow_nested = false,
	},

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

	symbols = {
		-- Control flow
		["if"] = "keyword",
		["then"] = "keyword",
		["else"] = "keyword",
		["elseif"] = "keyword",
		["unless"] = "keyword",
		["switch"] = "keyword",
		["when"] = "keyword",
		["for"] = "keyword",
		["while"] = "keyword",
		["repeat"] = "keyword",
		["until"] = "keyword",
		["break"] = "control",
		["continue"] = "control",
		["return"] = "control",
		["do"] = "keyword",
		["in"] = "keyword",

		-- Declarations
		["class"] = "keyword",
		["export"] = "keyword",
		["import"] = "keyword",
		["from"] = "keyword",
		["as"] = "keyword",
		["local"] = "keyword",
		["with"] = "keyword",
		["using"] = "keyword",
		["new"] = "keyword",

		-- Special references
		["extends"] = "keyword2",
		["super"] = "keyword2",
		["self"] = "keyword2",

		-- Logic
		["and"] = "keyword",
		["or"] = "keyword",
		["not"] = "keyword",

		-- Literals
		["true"] = "literal",
		["false"] = "literal",
		["nil"] = "literal",

		-- Common builtin
		["require"] = "preprocessor",
	},
})
