/**
 * YARA-L language support for CodeMirror 6
 * Extracted from countermeasure-web query.ts
 */

import { StreamLanguage, LanguageSupport } from '@codemirror/language'
import { type Completion } from '@codemirror/autocomplete'

const KEYWORDS = [
  'rule',
  'meta',
  'events',
  'event',
  'match',
  'outcome',
  'condition',
  'options',
  'strings',
  'import',
  'private',
  'global',
]

const OPERATORS = [
  'and',
  'or',
  'not',
  'of',
  'them',
  'any',
  'all',
  'within',
  'before',
  'after',
  'over',
]

const yaralLanguage = StreamLanguage.define({
  token(stream): string | null {
    if (stream.eatSpace()) {
      return null
    }

    if (stream.match(/\/\/.*$/) !== null) {
      return 'comment'
    }

    if (stream.match(/\/\*.*?\*\//) !== null) {
      return 'comment'
    }

    if (stream.match(/"(?:[^"\\]|\\.)*"/) !== null) {
      return 'string'
    }

    if (stream.match(/\d+(\.\d+)?/) !== null) {
      return 'number'
    }

    if (stream.match(/[A-Za-z_][\w.]*/) !== null) {
      const word = stream.current().toLowerCase()
      if (KEYWORDS.includes(word)) {
        return 'keyword'
      }
      if (OPERATORS.includes(word)) {
        return 'operator'
      }
      return 'variableName'
    }

    if (stream.match(/==|!=|<=|>=|[<>|=]/) !== null) {
      return 'operator'
    }

    stream.next()
    return null
  },
})

/** YARA-L language support for CodeMirror */
export function yaral(): LanguageSupport {
  return new LanguageSupport(yaralLanguage)
}

/** Static completions for YARA-L keywords and operators */
export const yaralCompletions: Completion[] = [
  ...KEYWORDS.map(label => ({ label, type: 'keyword' as const })),
  ...OPERATORS.map(label => ({ label, type: 'keyword' as const })),
]

export { yaralLanguage }
