///| Maps the syntax layer's `@syntax.HighlightTag` onto Monaco's packed token
/// metadata word and the matching `mtk` theme color map.
///
/// Monaco decouples *what* a token is (a `HighlightTag`, Monarch/TextMate scope,
/// …) from *how* it is encoded for rendering: the renderer only ever sees a
/// 32-bit metadata word (`encoded_token_attributes.mbt`) and resolves its class
/// (`mtk`) against a theme color map. This module is that
/// bridge for the production lexers. It assigns each tag a stable foreground
/// `ColorId` (and, for comments / strings / regexps, a `StandardTokenType`),
/// then packs it via the `MetadataConsts` offsets.
///
/// The richness of `HighlightTag` (Keyword vs Type vs Function …) lives in the
/// 9-bit foreground field, not the 2-bit `StandardTokenType`, so the whole tag
/// set fits the word with no information loss.

///|
/// Theme foreground `ColorId`s. `1`/`2` are Monaco's reserved default
/// foreground/background (`encoded_token_attributes.mbt`); token colors start at
/// `3`. Indices are the positions into `default_token_color_map`.
const COLOR_ID_KEYWORD : Int32 = 3

///|
const COLOR_ID_VARIABLE : Int32 = 4

///|
const COLOR_ID_STRING : Int32 = 5

///|
const COLOR_ID_NUMBER : Int32 = 6

///|
const COLOR_ID_COMMENT : Int32 = 7

///|
const COLOR_ID_PUNCTUATION : Int32 = 8

///|
const COLOR_ID_TYPE : Int32 = 9

///|
const COLOR_ID_FUNCTION : Int32 = 10

///|
const COLOR_ID_STRING_ESCAPE : Int32 = 11

///|
const COLOR_ID_REGEXP : Int32 = 12

///|
const COLOR_ID_INVALID : Int32 = 13

///|
/// The foreground `ColorId` assigned to a tag. Groupings mirror the legacy
/// `tokens.css` palette (e.g. punctuation/operator/delimiter share one color,
/// constant/tag track the keyword color) so the post-flip output is the same
/// colors under different class names.
fn tag_foreground_color_id(tag : @syntax.HighlightTag) -> Int32 {
  match tag {
    Keyword | Constant | Tag => COLOR_ID_KEYWORD
    Identifier | Variable | Attribute => COLOR_ID_VARIABLE
    String => COLOR_ID_STRING
    Number => COLOR_ID_NUMBER
    Comment | CommentDoc => COLOR_ID_COMMENT
    Punctuation | Operator | Delimiter => COLOR_ID_PUNCTUATION
    Plain => @common_tokens.COLOR_ID_DEFAULT_FOREGROUND
    Type => COLOR_ID_TYPE
    Function => COLOR_ID_FUNCTION
    StringEscape => COLOR_ID_STRING_ESCAPE
    Regexp => COLOR_ID_REGEXP
    Invalid => COLOR_ID_INVALID
  }
}

///|
/// The 2-bit `StandardTokenType` for a tag. Only comments, strings and regexps
/// carry a non-`Other` type (Monaco uses these for bracket matching, electric
/// characters, autoclosing, …); every other tag's identity is in its color.
fn tag_standard_token_type(tag : @syntax.HighlightTag) -> Int32 {
  match tag {
    Comment | CommentDoc => @common_tokens.STANDARD_TOKEN_TYPE_COMMENT
    String | StringEscape => @common_tokens.STANDARD_TOKEN_TYPE_STRING
    Regexp => @common_tokens.STANDARD_TOKEN_TYPE_REGEX
    _ => @common_tokens.STANDARD_TOKEN_TYPE_OTHER
  }
}

///|
/// Packs a `HighlightTag` into a Monaco token metadata word: foreground color id
/// + font style + standard token type + language id, via the `MetadataConsts`
/// offsets. The background field is set to the default so the word matches
/// `LineTokens::default_token_metadata` for fields the renderer ignores.
fn tag_to_metadata(
  tag : @syntax.HighlightTag,
  font_style~ : Int32 = @common_tokens.FONT_STYLE_NONE,
  language_id~ : Int32 = 0,
) -> UInt32 {
  ((language_id << @common_tokens.METADATA_LANGUAGEID_OFFSET) |
  (tag_standard_token_type(tag) << @common_tokens.METADATA_TOKEN_TYPE_OFFSET) |
  (font_style << @common_tokens.METADATA_FONT_STYLE_OFFSET) |
  (tag_foreground_color_id(tag) << @common_tokens.METADATA_FOREGROUND_OFFSET) |
  (
    @common_tokens.COLOR_ID_DEFAULT_BACKGROUND <<
    @common_tokens.METADATA_BACKGROUND_OFFSET
  )).reinterpret_as_uint()
}

///|
/// The production color map: `colorId -> CSS color`, indexed by foreground
/// `ColorId`. Reuses the workbench `--vscode-token-*` custom properties so the
/// `mtk` classes render in the same colors as the legacy `tok-*` classes.
/// Mirrors Monaco's `TokenizationRegistry.getColorMap()` result.
pub fn default_token_color_map() -> Array[String] {
  [
    "", // 0  ColorId.None
     "var(--vscode-editor-foreground)", // 1  default foreground
     "var(--vscode-editor-background)", // 2  default background
     "var(--vscode-token-keyword)", // 3  COLOR_ID_KEYWORD
     "var(--vscode-token-variable)", // 4  COLOR_ID_VARIABLE
     "var(--vscode-token-string)", // 5  COLOR_ID_STRING
     "var(--vscode-token-number)", // 6  COLOR_ID_NUMBER
     "var(--vscode-token-comment)", // 7  COLOR_ID_COMMENT
     "var(--vscode-token-punctuation)", // 8  COLOR_ID_PUNCTUATION
     "var(--vscode-token-type)", // 9  COLOR_ID_TYPE
     "var(--vscode-token-function)", // 10 COLOR_ID_FUNCTION
     "var(--vscode-token-string-escape)", // 11 COLOR_ID_STRING_ESCAPE
     "var(--vscode-token-regexp)", // 12 COLOR_ID_REGEXP
     "var(--vscode-token-invalid)", // 13 COLOR_ID_INVALID
  ]
}