// Vadalog Language Mode for CodeMirror 6

import { StreamLanguage, LanguageSupport } from '@codemirror/language';
// Uncomment these imports if you want to enable custom color override:
// import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
// import { tags as t } from '@lezer/highlight';
// import { Prec } from '@codemirror/state';

export const MODE_NAME = 'vadalog';
export const NAME = 'vadalog';
export const MIME = 'text/x-vadalog';
export const FILE_EXTENSIONS = ['vada', 'vadalog'];

const vadalogLanguage = StreamLanguage.define({
  name: MODE_NAME,
  
  startState() {
    return {};
  },

  token(stream) {
    if (stream.eatSpace()) {
      return null;
    }

    // Comments - grey italic
    if (stream.match(/^%.*$/)) {
      return 'comment';
    }

    // Annotations - bold green
    // @input, @output, @bind, @mapping, etc.
    if (stream.match(/^@[a-z][a-z0-9_]*/)) {
      return 'meta';
    }

    // Skolem functions (FUNCTION_NAME) - cyan
    // #FUNC, #PERSON, etc. (# followed by 2+ uppercase letters)
    if (stream.match(/^#[A-Z]{2,}/)) {
      return 'property';
    }

    // Strings - blue (normal)
    // Double-quoted strings (support escaped quotes "")
    if (stream.match(/^"(?:[^"]|"")*"/)) {
      return 'string';
    }

    // Numbers - blue (normal) and blue (normal)
    // Doubles (with decimal point) return 'number', integers return 'string'
    if (stream.match(/^-?\d+\.\d+/)) {
      return 'number';
    }
    if (stream.match(/^-?\d+/)) {
      return 'string';
    }

    // Punctuation - strong black
    // Parentheses, commas, dots
    if (stream.match(/^[().,]/)) {
      return 'strong';
    }

    // Operators - purple
    // Multi-character operators first (order matters!)
    if (stream.match(/^(?::-|->|<=|>=|==|!=|<>|&&|\|\||!in)\b/)) {
      return 'operator';
    }
    // Single-character operators (excluding punctuation handled above)
    if (stream.match(/^[<>=+\-*\/|&!;\[\]{}]/)) {
      return 'operator';
    }
    // Keyword operators: 'not' followed by space, 'in' with word boundary
    if (stream.match(/^not(?=\s)/)) {
      return 'operator';
    }
    if (stream.match(/^in\b/)) {
      return 'operator';
    }

    // External functions with namespace (collections:add, nullManagement:isnull, etc.) - cyan
    // Must check BEFORE regular atoms since they contain colons
    // Match pattern: lowercase_word:word (can have multiple colons)
    if (stream.match(/^[a-z][a-z0-9_:<>]*:[a-z0-9_:<>]+/)) {
      return 'property';
    }

    // Built-in functions (expressions) - cyan
    const functions = /^(?:msum|mprod|mcount|munion|mmax|mmin|mavg|union|list|set|min|max|sum|prod|avg|count|maxcount|substring|contains|starts_with|ends_with|concat|concat_ws|string_length|is_empty|to_lower|to_upper|split|index_of|replace|join|and|or|not|xor|nand|nor|xnor|implies|iff|if|struct|is_null|is_not_null|monotonically_increasing_id|transform|filter|uuid|as_string|as_double|as_int|as_long|as_float|as_boolean|as_list|as_set|as_map|as_date|as_timestamp|as_json|between|_between|between_|_between_|mask)\b/;
    if (stream.match(functions)) {
      return 'property';
    }

    // Variables - orange
    // Uppercase identifiers (can contain underscores and numbers)
    if (stream.match(/^[A-Z][A-Za-z0-9_]*/)) {
      return 'builtin';
    }

    // Atoms (predicates) - green
    // Lowercase identifiers without colons (can contain uppercase in camelCase)
    if (stream.match(/^[a-z][a-zA-Z0-9_<>]*/)) {
      return 'tag';
    }

    // Everything else is black (no styling)
    stream.next();
    return null;
  },

  languageData: {
    commentTokens: { line: '%' }
  }
});

// CUSTOM COLOR OVERRIDE (currently disabled)
// To enable custom RED color for 'keyword' tokens, uncomment below:
// const redKeywordStyle = HighlightStyle.define([
//   { tag: t.keyword, color: 'red', fontWeight: 'bold' }
// ]);

export function vadalog(): LanguageSupport {
  return new LanguageSupport(vadalogLanguage);
  // To enable custom color override, use:
  // return new LanguageSupport(vadalogLanguage, [
  //   Prec.highest(syntaxHighlighting(redKeywordStyle))
  // ]);
}

export const vadalogLanguageSupport = vadalog();

export function getVadalogLanguage(): LanguageSupport {
  return vadalogLanguageSupport;
}
