/**
 * LaTeX Monarch Tokenizer for Monaco Editor.
 * Provides syntax highlighting for LaTeX documents.
 */
import type { languages } from 'monaco-editor';

// Built-in LaTeX commands for syntax highlighting
const builtin = [
    'addcontentsline',
    'addtocontents',
    'addtocounter',
    'address',
    'addtolength',
    'addvspace',
    'alph',
    'appendix',
    'arabic',
    'author',
    'backslash',
    'baselineskip',
    'baselinestretch',
    'bf',
    'bibitem',
    'bigskipamount',
    'bigskip',
    'boldmath',
    'boldsymbol',
    'cal',
    'caption',
    'cdots',
    'centering',
    'chapter',
    'circle',
    'cite',
    'cleardoublepage',
    'clearpage',
    'cline',
    'closing',
    'color',
    'copyright',
    'dashbox',
    'date',
    'ddots',
    'documentclass',
    'domlinecolor',
    'dotfill',
    'em',
    'emph',
    'ensuremath',
    'epigraph',
    'euro',
    'fbox',
    'flushbottom',
    'fnsymbol',
    'footnote',
    'footnotemark',
    'footnotesize',
    'footnotetext',
    'frac',
    'frame',
    'framebox',
    'frenchspacing',
    'hfill',
    'hline',
    'href',
    'hrulefill',
    'hspace',
    'huge',
    'Huge',
    'hyphenation',
    'include',
    'includegraphics',
    'includeonly',
    'indent',
    'input',
    'it',
    'item',
    'kill',
    'label',
    'large',
    'Large',
    'LARGE',
    'LaTeX',
    'LaTeXe',
    'ldots',
    'left',
    'lefteqn',
    'line',
    'linebreak',
    'linethickness',
    'linewidth',
    'listoffigures',
    'listoftables',
    'location',
    'makebox',
    'maketitle',
    'markboth',
    'mathcal',
    'mathop',
    'mbox',
    'medskip',
    'multicolumn',
    'multiput',
    'newcommand',
    'newcolumntype',
    'newcounter',
    'newenvironment',
    'newfont',
    'newlength',
    'newline',
    'newpage',
    'newsavebox',
    'newtheorem',
    'nocite',
    'noindent',
    'nolinebreak',
    'nonfrenchspacing',
    'normalsize',
    'nopagebreak',
    'not',
    'onecolumn',
    'opening',
    'oval',
    'overbrace',
    'overline',
    'pagebreak',
    'pagenumbering',
    'pageref',
    'pagestyle',
    'par',
    'paragraph',
    'parbox',
    'parindent',
    'parskip',
    'part',
    'protect',
    'providecommand',
    'put',
    'raggedbottom',
    'raggedleft',
    'raggedright',
    'raisebox',
    'ref',
    'renewcommand',
    'right',
    'rm',
    'roman',
    'rule',
    'savebox',
    'sbox',
    'sc',
    'scriptsize',
    'section',
    'setcounter',
    'setlength',
    'settowidth',
    'sf',
    'shortstack',
    'signature',
    'sl',
    'slash',
    'small',
    'smallskip',
    'sout',
    'space',
    'sqrt',
    'stackrel',
    'stepcounter',
    'subparagraph',
    'subsection',
    'subsubsection',
    'tableofcontents',
    'telephone',
    'TeX',
    'textbf',
    'textcolor',
    'textit',
    'textmd',
    'textnormal',
    'textrm',
    'textsc',
    'textsf',
    'textsl',
    'texttt',
    'textup',
    'textwidth',
    'textheight',
    'thanks',
    'thispagestyle',
    'tiny',
    'title',
    'today',
    'tt',
    'twocolumn',
    'typeout',
    'typein',
    'uline',
    'underbrace',
    'underline',
    'unitlength',
    'usebox',
    'usecounter',
    'uwave',
    'value',
    'vbox',
    'vcenter',
    'vdots',
    'vector',
    'verb',
    'vfill',
    'vline',
    'vphantom',
    'vspace',
    'RequirePackage',
    'NeedsTeXFormat',
    'usepackage',
    'documentstyle',
    'def',
    'edef',
    'defcommand',
    'if',
    'ifdim',
    'ifnum',
    'ifx',
    'fi',
    'else',
    'begingroup',
    'endgroup',
    'definecolor',
    'eifstrequal',
    'eeifstrequal',
];

export const monarchTokenizer: languages.IMonarchLanguage = {
    defaultToken: '',
    tokenPostfix: '.latex',
    displayName: 'LaTeX',
    name: 'latex',
    mimeTypes: ['text/latex', 'text/tex'],
    fileExtensions: ['tex', 'sty', 'cls'],
    lineComment: '% ',
    builtin,
    tokenizer: {
        root: [
            // Environment begin/end
            [
                '(\\\\begin)(\\s*)(\\{)([\\w\\-\\*\\@]+)(\\})',
                [
                    'keyword.predefined',
                    'white',
                    '@brackets',
                    {
                        token: 'tag.env-$4',
                        bracket: '@open',
                    },
                    '@brackets',
                ],
            ],
            [
                '(\\\\end)(\\s*)(\\{)([\\w\\-\\*\\@]+)(\\})',
                [
                    'keyword.predefined',
                    'white',
                    '@brackets',
                    {
                        token: 'tag.env-$4',
                        bracket: '@close',
                    },
                    '@brackets',
                ],
            ],
            // Escaped characters
            ['\\\\[^a-zA-Z@]', 'keyword'],
            // @ commands
            ['\\@[a-zA-Z@]+', 'keyword.at'],
            // Commands
            [
                '\\\\([a-zA-Z@]+)',
                {
                    cases: {
                        '$1@builtin': 'keyword.predefined',
                        '@default': 'keyword',
                    },
                },
            ],
            { include: '@whitespace' },
            // Brackets
            ['[{}()\\[\\]]', '@brackets'],
            // Arguments
            ['#+\\d', 'number.arg'],
            // Dimensions
            ['\\-?(?:\\d+(?:\\.\\d+)?|\\.\\d+)\\s*(?:em|ex|pt|pc|sp|cm|mm|in)', 'number.len'],
        ],
        whitespace: [
            ['[ \\t\\r\\n]+', 'white'],
            ['%.*$', 'comment'],
        ],
    },
};

export default monarchTokenizer;
