#include <eepp/ui/doc/languages/objective-c.hpp>
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp>

namespace EE { namespace UI { namespace Doc { namespace Language {

SyntaxDefinition& addObjectiveC() {

	auto& sd = SyntaxDefinitionManager::instance()->add(

		{ "Objective-C",
		  { "%.m$" },
		  {
			  { { "//.-\n" }, "comment" },
			  { { "/%*", "%*/" }, "comment" },
			  { { "(#%s*include)%s+([<%\"][%w%d%.%\\%/%_%-]+[>%\"])" },
				{ "keyword", "keyword", "literal" } },
			  { { "(#%s*import)%s+([<%\"][%w%d%.%\\%/%_%-]+[>%\"])" },
				{ "keyword", "keyword", "literal" } },
			  { { "\"", "[\"\n]", "\\" }, "string" },
			  { { "'", "'", "\\" }, "string" },
			  { { "c_number_parser" }, "number", "", SyntaxPatternMatchType::Parser },
			  { { "[%+%-=/%*%^%%<>!~|&]" }, "operator" },
			  { { "(if|for|while|switch|sizeof|_Alignof|defined)\\s*(?=\\()" },
				{ "normal", "keyword", "keyword" },
				"",
				SyntaxPatternMatchType::RegEx },
			  { { "[%a_][%w_]*%f[(]" }, "function" },
			  { { "[@#]?[%a_][%w_]*" }, "symbol" },

		  },
		  {

			  // C
			  { "elseif", "keyword" },
			  { "int", "type" },
			  { "then", "keyword" },
			  { "unsigned", "type" },
			  { "continue", "keyword" },
			  { "default", "keyword" },
			  { "volatile", "keyword" },
			  { "switch", "keyword" },
			  { "char", "type" },
			  { "double", "type" },
			  { "auto", "keyword" },
			  { "bool", "type" },
			  { "return", "keyword" },
			  { "extern", "keyword" },
			  { "NULL", "literal" },
			  { "long", "type" },
			  { "void", "keyword" },
			  { "union", "keyword" },
			  { "short", "type" },
			  { "static", "keyword" },
			  { "inline", "keyword" },
			  { "false", "literal" },
			  { "for", "keyword" },
			  { "goto", "keyword" },
			  { "while", "keyword" },
			  { "const", "keyword" },
			  { "int32_t", "type" },
			  { "int16_t", "type" },
			  { "uint16_t", "type" },
			  { "typedef", "keyword" },
			  { "true", "literal" },
			  { "else", "keyword" },
			  { "uint32_t", "type" },
			  { "enum", "keyword" },
			  { "int8_t", "type" },
			  { "int64_t", "type" },
			  { "float", "type" },
			  { "struct", "keyword" },
			  { "break", "keyword" },
			  { "uint8_t", "type" },
			  { "uint64_t", "type" },
			  { "case", "keyword" },
			  { "if", "keyword" },
			  { "do", "keyword" },
			  { "constexpr", "keyword" },

			  { "signed", "type" },
			  { "_BitInt", "type" },
			  { "_Bool", "type" },
			  { "bool", "type" },
			  { "_Complex", "type" },
			  { "complex", "type" },
			  { "_Imaginary", "type" },
			  { "imaginary", "type" },
			  { "_Decimal128", "type" },
			  { "_Decimal32", "type" },
			  { "_Decimal64", "type" },
			  { "int_least8_t", "type" },
			  { "int_least16_t", "type" },
			  { "int_least32_t", "type" },
			  { "int_least64_t", "type" },
			  { "uint_least8_t", "type" },
			  { "uint_least16_t", "type" },
			  { "uint_least32_t", "type" },
			  { "uint_least64_t", "type" },
			  { "int_fast8_t", "type" },
			  { "int_fast16_t", "type" },
			  { "int_fast32_t", "type" },
			  { "int_fast64_t", "type" },
			  { "uint_fast8_t", "type" },
			  { "uint_fast16_t", "type" },
			  { "uint_fast32_t", "type" },
			  { "uint_fast64_t", "type" },
			  { "intptr_t", "type" },
			  { "uintptr_t", "type" },
			  { "intmax_t", "type" },
			  { "uintmax_t", "type" },
			  { "size_t", "type" },
			  { "ptrdiff_t", "type" },
			  { "max_align_t", "type" },
			  { "wchar_t", "type" },
			  { "nullptr_t", "type" },
			  { "imaxdiv_t", "type" },
			  { "atomic_bool", "type" },
			  { "atomic_char", "type" },
			  { "atomic_schar", "type" },
			  { "atomic_uchar", "type" },
			  { "atomic_short", "type" },
			  { "atomic_ushort", "type" },
			  { "atomic_int", "type" },
			  { "atomic_uint", "type" },
			  { "atomic_long", "type" },
			  { "atomic_ulong", "type" },
			  { "atomic_llong", "type" },
			  { "atomic_ullong", "type" },
			  { "atomic_char16_t", "type" },
			  { "atomic_char32_t", "type" },
			  { "atomic_wchar_t", "type" },
			  { "atomic_int_least8_t", "type" },
			  { "atomic_uint_least8_t", "type" },
			  { "atomic_int_least16_t", "type" },
			  { "atomic_uint_least16_t", "type" },
			  { "atomic_int_least32_t", "type" },
			  { "atomic_uint_least32_t", "type" },
			  { "atomic_int_least64_t", "type" },
			  { "atomic_uint_least64_t", "type" },
			  { "atomic_int_fast8_t", "type" },
			  { "atomic_uint_fast8_t", "type" },
			  { "atomic_int_fast16_t", "type" },
			  { "atomic_uint_fast16_t", "type" },
			  { "atomic_int_fast32_t", "type" },
			  { "atomic_uint_fast32_t", "type" },
			  { "atomic_int_fast64_t", "type" },
			  { "atomic_uint_fast64_t", "type" },
			  { "atomic_intptr_t", "type" },
			  { "atomic_uintptr_t", "type" },
			  { "atomic_size_t", "type" },
			  { "atomic_ptrdiff_t", "type" },
			  { "atomic_intmax_t", "type" },
			  { "atomic_uintmax_t", "type" },
			  { "memory_order_relaxed", "type" },
			  { "memory_order_consume", "type" },
			  { "memory_order_acquire", "type" },
			  { "memory_order_release", "type" },
			  { "memory_order_acq_rel", "type" },
			  { "memory_order_seq_cst", "type" },
			  { "memory_order", "type" },
			  { "atomic_flag", "type" },
			  { "FILE", "type" },
			  { "fpos_t", "type" },

			  { "#if", "keyword" },
			  { "#ifdef", "keyword" },
			  { "#ifndef", "keyword" },
			  { "#elif", "keyword" },
			  { "#else", "keyword" },
			  { "#endif", "keyword" },
			  { "#define", "keyword" },
			  { "#undef", "keyword" },
			  { "#include", "keyword" },
			  { "#line", "keyword" },
			  { "#error", "keyword" },
			  { "#pragma", "keyword" },
			  { "#warning ", "keyword" },
			  { "#elifdef ", "keyword" },
			  { "#elifndef ", "keyword" },
			  { "#embed ", "keyword" },

			  // Objective-C
			  { "retain", "keyword" },
			  { "release", "keyword" },
			  { "autorelease", "keyword" },
			  { "@interface", "keyword" },
			  { "@implementation", "keyword" },
			  { "@protocol", "keyword" },
			  { "@end", "keyword" },
			  { "@class", "keyword" },
			  { "@property", "keyword" },
			  { "@synthesize", "keyword" },
			  { "@dynamic", "keyword" },
			  { "@autoreleasepool", "keyword" },
			  { "@try", "keyword" },
			  { "@catch", "keyword" },
			  { "@finally", "keyword" },
			  { "@throw", "keyword" },
			  { "@public", "keyword" },
			  { "@protected", "keyword" },
			  { "@private", "keyword" },
			  { "@package", "keyword" },
			  { "@selector", "keyword" },
			  { "@synchronized", "keyword" },
			  { "@optional", "keyword" },
			  { "@required", "keyword" },
			  { "@encode", "keyword" },
			  { "id", "type" },
			  { "Class", "type" },
			  { "SEL", "type" },
			  { "nil", "literal" },
			  { "Nil", "literal" },
			  { "YES", "literal" },
			  { "NO", "literal" },
			  { "strong", "keyword" },
			  { "weak", "keyword" },
			  { "copy", "keyword" },
			  { "nonatomic", "keyword" },
			  { "assign", "keyword" },
			  { "unsafe_unretained", "keyword" },
			  { "bycopy", "keyword" },
			  { "byref", "keyword" },
			  { "in", "keyword" },
			  { "out", "keyword" },
			  { "inout", "keyword" },
			  { "readonly", "keyword" } },

		  "//",
		  {}

		} );

	sd.setFoldRangeType( FoldRangeType::Braces ).setFoldBraces( { { '{', '}' } } );
	sd.setBlockComment( { "/*", "*/" } );
	sd.addAlternativeName( "objc" );
	return sd;
}

}}}} // namespace EE::UI::Doc::Language
