import type { HLJSApi, Language } from "highlight.js";

/* vim:set ts=2 sw=2 et: */

/*
    Source: https://gitea.osmocom.org/ttcn3/highlightjs-ttcn3/src/branch/master/ttcn3.js

    Language: TTCN-3
    Description: TTCN-3 is a domain specific programming language used particularly (but not only) in the telecom domain.
    Website: http://www.ttcn-3.org/
    Category: common, protocols
    Spec: ETSI ES 201 873-1 V4.15.1
    Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
*/

export default function(hljs: HLJSApi): Language {
  const RESERVED_WORDS = [ /* table A.3 */
    'action',
    'activate',
    'address',
    'alive',
    'all',
    'alt',
    'altstep',
    'and',
    'and4b',
    'any',
    'anytype',
    'bitstring',
    'boolean',
    'break',
    'case',
    'call',
    'catch',
    'char',
    'charstring',
    'check',
    'clear',
    'complement',
    'component',
    'connect',
    'const',
    'continue',
    'control',
    'create',
    'deactivate',
    'decmatch',
    'default',
    'disconnect',
    'display',
    'do',
    'done',
    'else',
    'encode',
    'enumerated',
    'error',
    'except',
    'exception',
    'execute',
    'extends',
    'extension',
    'external',
    'fail',
    'false',
    'float',
    'for',
    'friend',
    'from',
    'function',
    'getverdict',
    'getcall',
    'getreply',
    'goto',
    'group',
    'halt',
    'hexstring',
    'if',
    'ifpresent',
    'import',
    'in',
    'inconc',
    'infinity',
    'inout',
    'integer',
    'interleave',
    'isbound',
    'ischosen',
    'ispresent',
    'isvalue',
    'kill',
    'killed',
    'label',
    'language',
    'length',
    'log',
    'map',
    'match',
    'message',
    'mixed',
    'mod',
    'modifies',
    'module',
    'modulepar',
    'mtc',
    'noblock',
    'none',
    'not',
    'not_a_number',
    'not4b',
    'nowait',
    'null',
    'octetstring',
    'of',
    'omit',
    'on',
    'optional',
    'or',
    'or4b',
    'out',
    'override',
    'param',
    'pass',
    'pattern',
    'permutation',
    'port',
    'present',
    'private',
    'procedure',
    'public',
    'raise',
    'read',
    'receive',
    'record',
    'recursive',
    'rem',
    'repeat',
    'reply',
    'return',
    'running',
    'runs',
    'select',
    'self',
    'send',
    'sender',
    'set',
    'setencode',
    'setverdict',
    'signature',
    'start',
    'stop',
    'subset',
    'superset',
    'system',
    'template',
    'testcase',
    'timeout',
    'timer',
    'to',
    'trigger',
    'true',
    'type',
    'union',
    'universal',
    'unmap',
    'value',
    'valueof',
    'var',
    'variant',
    'verdicttype',
    'while',
    'with',
    'xor',
    'xor4b',
  ];

  const BUILT_INS = [
    'action',
    'activate',
    'any2unistr',
    'bit2hex',
    'bit2int',
    'bit2oct',
    'bit2str',
    'call',
    'catch',
    'char2int',
    'char2oct',
    'check',
    'clear',
    'complement',
    'connect',
    'create',
    'deactivate',
    'decmatch',
    'decvalue',
    'decvalue_o',
    'decvalue_unichar',
    'disconnect',
    'encode',
    'encvalue',
    'encvalue_o',
    'encvalue_unichar',
    'enum2int',
    'execute',
    'float2int',
    'get_stringencoding',
    'getcall',
    'getreply',
    'getverdict',
    'halt',
    'hex2bit',
    'hex2int',
    'hex2oct',
    'hex2str',
    'hostid',
    'int2bit',
    'int2char',
    'int2enum',
    'int2float',
    'int2hex',
    'int2oct',
    'int2str',
    'int2unichar',
    'isbound',
    'ischosen',
    'ispresent',
    'istemplatekind',
    'isvalue',
    'kill',
    'killed',
    'length',
    'lengthof',
    'log',
    'map',
    'match',
    'oct2bit',
    'oct2char',
    'oct2hex',
    'oct2int',
    'oct2str',
    'oct2unichar',
    'raise',
    'receive',
    'record',
    'regexp',
    'remove_bom',
    'replace',
    'reply',
    'rnd',
    'running',
    'send',
    'setencode',
    'setverdict',
    'sizeof',
    'start',
    'stop',
    'str2float',
    'str2hex',
    'str2int',
    'str2oct',
    'substr',
    'testcasename',
    'timeout',
    'trigger',
    'unichar2int',
    'unichar2oct',
    'unmap',
    'value',
    'valueof',
  ];

  const LITERALS = [
    'error',
    'fail',
    'false',
    'inconc',
    'infinity',
    'none',
    'null',
    'omit',
    'pass',
    'true',
  ];

  const TYPES = [
    'address',
    'anytype',
    'bitstring',
    'boolean',
    'charstring',
    'default',
    'float',
    'hexstring',
    'integer',
    'octetstring',
    'universal',
    'universal charstring',
    'verdicttype',
  ];

  const KEYWORDS = {
    keyword: RESERVED_WORDS,
    built_in: BUILT_INS,
    literal: LITERALS,
    type: TYPES,
  };

  const STRING = {
    className: 'string',
    variants: [
      { /* octstring */
        match: /'([a-fA-F0-9]{2}|\?|\*)*'O/,
        relevance: 10,
      },
      { /* hexstring */
        match: /'[a-fA-F0-9\?\*]*'H/,
        relevance: 10,
      },
      { /* bitstring */
        match: /'[01\?\*]*'B/,
        relevance: 10,
      },
      hljs.APOS_STRING_MODE,
      hljs.QUOTE_STRING_MODE,
    ],
  };

  return {
    name: 'TTCN-3',
    aliases: [
      'ttcn',
      'ttcn3',
      'ttcnpp',
    ],
    keywords: KEYWORDS,
    illegal: '(\\*=|\\+=|-=)',
    contains: [
      hljs.C_BLOCK_COMMENT_MODE,
      hljs.C_LINE_COMMENT_MODE,
      STRING,
    ]
  };
}
