///|
/// 容器帧的类型。
priv enum FrameKind {
  Obj
  Arr
}

///|
/// 当前语法上下文:下一个非空白字节应该是什么。
priv enum Ctx {
  /// 文档尚未开始,期待根值。
  RootStart
  /// 根值已完成,只允许空白。
  RootDone
  /// 对象内:期待键或 `}`。
  ObjKeyOrEnd
  /// 对象内 `,` 之后:只允许键。
  ObjKey
  /// 键之后:期待 `:`。
  ObjColon
  /// `:` 之后:期待值。
  ObjValue
  /// 成员值之后:期待 `,` 或 `}`。
  ObjCommaOrEnd
  /// 数组内:期待值或 `]`。
  ArrValueOrEnd
  /// 数组内 `,` 之后:期待值。
  ArrValue
  /// 元素值之后:期待 `,` 或 `]`。
  ArrCommaOrEnd
}

///|
/// 词法子状态。
priv enum LexKind {
  /// 结构化扫描(空白与结构字符)。
  LexNormal
  /// 字符串内部。
  LexStr
  /// 反斜杠之后。
  LexStrEscape
  /// `\uXXXX` 已读 n 位。
  LexStrHex(Int, Int)
  /// 已读到高位代理,等待 `\`。
  LexStrLowSlash(Int)
  /// 已读到高位代理,等待 `u`。
  LexStrLowU(Int)
  /// 低位代理的 4 位十六进制,已读 n 位。
  LexStrLowHex(Int, Int, Int)
  /// 数字内部。
  LexNum
  /// true / false / null 逐字匹配,已匹配 matched 个字符。
  LexLit(LitKind, Int)
}

///|
/// 字面量种类。
priv enum LitKind {
  LitTrue
  LitFalse
  LitNull
}

///|
/// 数字词法子状态。
priv enum NumState {
  /// 刚读到 `-`。
  NumSign
  /// 整数部分为 `0`。
  NumZero
  /// 整数部分已有非零起始数字。
  NumInt
  /// 刚读到 `.`。
  NumDot
  /// 小数部分至少一位。
  NumFrac
  /// 刚读到 `e` / `E`。
  NumExp
  /// 刚读到指数符号。
  NumExpSign
  /// 指数至少一位数字。
  NumExpDigits
}

///|
/// 一个已打开的容器。
priv struct Frame {
  kind : FrameKind
  /// 已完成的成员(对象)或元素(数组)数量。
  mut count : Int
  /// 已出现的键,用于重复键检测。
  keys : Map[String, Unit]
  /// 该容器的路径。
  path : Path
  /// 该键对应的值路径。键完成时算一次,值事件直接复用,避免重复分配。
  mut pending_path : Path
}

///|
/// 增量 JSON 解析器。
///
/// 它消费**已经提取出来的参数片段字节**,不负责连接模型或解析 SSE。
/// 同一个解析器实例只处理一个 JSON 文档。
///
/// 内部状态收在一个私有类型的字段里:`.mbti` 只显示这一个不透明字段,
/// 改动它的内部字段不会改变公开接口(改类型名会)。
pub struct Parser {
  inner : ParserState
}

///|
/// 解析器的全部可变状态。私有实现细节,不是可用 API。
struct ParserState {
  limits : Limits
  mut ctx : Ctx
  frames : Array[Frame]
  mut lex : LexKind
  mut num_state : NumState
  /// 已消费的绝对字节数。
  mut offset : Int
  mut total_bytes : Int
  mut node_count : Int
  mut finished : Bool
  mut events : Array[Event]
  /// 收到的全部原始字节,用于构造 `CompletedDocument`。
  raw : Array[Byte]
  /// 当前字符串已解码的内容。
  str_buf : StringBuilder
  /// 本次 `feed` 尚未交付的字符串增量。
  str_delta : StringBuilder
  /// 当前数字的原始词法。
  num_buf : StringBuilder
  /// 当前 token 的起始绝对偏移。
  mut token_start : Int
  /// 当前 token 已消费的字节数。
  mut token_bytes : Int
  /// 当前字符串是否是对象键。
  mut in_key : Bool
  /// 当前正在读取的值的路径。
  mut cur_path : Path
  /// UTF-8 待续字节(存 Int 以避免 Byte 转换)。
  utf8_pending : Array[Int]
  mut utf8_expected : Int
  mut utf8_start : Int
}

///|
/// 创建解析器。限制不合法时抛出 `InvalidLimits`。
///
/// ```mbt check
/// test {
///   let parser = Parser::new()
///   let events = parser.feed(b"{\"city\":")
///   inspect(events.length(), content="2")
/// }
/// ```
pub fn Parser::new(limits? : Limits) -> Parser raise ParseError {
  let limits = match limits {
    Some(l) => l
    None => Limits::strict()
  }
  validate_limits(
    max_depth=limits.max_depth,
    max_token_bytes=limits.max_token_bytes,
    max_nodes=limits.max_nodes,
    max_total_bytes=limits.max_total_bytes,
  )
  let inner : ParserState = {
    limits,
    ctx: RootStart,
    frames: [],
    lex: LexNormal,
    num_state: NumZero,
    offset: 0,
    total_bytes: 0,
    node_count: 0,
    finished: false,
    events: [],
    raw: [],
    str_buf: StringBuilder::new(),
    str_delta: StringBuilder::new(),
    num_buf: StringBuilder::new(),
    token_start: 0,
    token_bytes: 0,
    in_key: false,
    cur_path: Path::root(),
    utf8_pending: [],
    utf8_expected: 0,
    utf8_start: -1,
  }
  { inner, }
}

///|
/// 已消费的绝对字节数。
pub fn Parser::offset(self : Parser) -> Int {
  self.inner.offset
}

///|
/// 当前生效的资源限制。
pub fn Parser::limits(self : Parser) -> Limits {
  self.inner.limits
}

///|
/// 是否已经 `finish`(无论结果是完成、未完成还是取消)。
///
/// 解析出错后也会返回 `true`:错误使解析器进入终止状态。
pub fn Parser::is_finished(self : Parser) -> Bool {
  self.inner.finished
}

///|
/// 消费一段输入,返回本次产生的结构事件。
///
/// 空块不改变语义。任何错误都会使解析器进入终止状态:之后再次 `feed`
/// 或 `finish` 抛出 `AlreadyFinished`。
pub fn Parser::feed(
  self : Parser,
  bytes : Bytes,
) -> Array[Event] raise ParseError {
  if self.inner.finished {
    raise ParseError::AlreadyFinished(op="feed")
  }
  try self.feed_inner(bytes) catch {
    err => {
      self.inner.finished = true
      raise err
    }
  } noraise {
    events => events
  }
}

///|
/// `feed` 的实际实现;任何抛出都由 `feed` 统一转为终止状态。
fn Parser::feed_inner(
  self : Parser,
  bytes : Bytes,
) -> Array[Event] raise ParseError {
  let n = bytes.length()
  let remaining = self.inner.limits.max_total_bytes - self.inner.total_bytes
  let accepted = if n < remaining { n } else { remaining }
  for k in 0.. self.step_normal(b, pos)
      LexStr => self.step_str(b, pos)
      LexStrEscape => self.step_escape(b, pos)
      LexStrHex(count, acc) => self.step_hex(b, pos, count, acc)
      LexStrLowSlash(hi) => self.step_low_slash(b, pos, hi)
      LexStrLowU(hi) => self.step_low_u(b, pos, hi)
      LexStrLowHex(count, hi, acc) => self.step_low_hex(b, pos, count, hi, acc)
      LexNum => consumed = self.step_num(b, pos)
      LexLit(kind, matched) => self.step_lit(b, pos, kind, matched)
    }
    if consumed {
      i += 1
      self.inner.offset += 1
    }
  }
  if accepted < n {
    raise ParseError::LimitExceeded(
      kind=LimitKind::TotalBytes,
      pos=self.inner.offset,
      allowed=self.inner.limits.max_total_bytes,
      actual=self.inner.limits.max_total_bytes + 1,
    )
  }
  self.flush_string_delta()
  self.inner.events
}

///|
/// 结束输入并判断文档是否完整合法。
///
/// 返回 `(收尾事件, 结果)`:一个恰好以数字结尾的文档,它的 `ValueComplete`
/// 只有在调用 `finish` 时才能被确认,所以收尾事件必须一并交付。
///
/// 只有 `EndOfStream` 可能返回 `Completed`;取消或截断返回 `Aborted`。
///
/// ```mbt check
/// test {
///   let parser = Parser::new()
///   let _ = parser.feed(b"[1")
///   let (events, result) = parser.finish()
///   // 末尾数字只有在 finish 时才能被确认,收尾事件一并交付。
///   inspect(events.length(), content="1")
///   inspect(result is FinishResult::Incomplete(..), content="true")
/// }
/// ```
pub fn Parser::finish(
  self : Parser,
  reason? : EndReason,
) -> (Array[Event], FinishResult) raise ParseError {
  if self.inner.finished {
    raise ParseError::AlreadyFinished(op="finish")
  }
  self.inner.finished = true
  self.inner.events = []
  let reason = match reason {
    Some(r) => r
    None => EndOfStream
  }
  let result = match reason {
    EndOfStream => self.finish_normal()
    _ => FinishResult::Aborted(reason~)
  }
  (self.inner.events, result)
}

///|
/// 正常结束路径:补齐可终结的 token,检查语法栈与 UTF-8 残留。
fn Parser::finish_normal(self : Parser) -> FinishResult raise ParseError {
  if self.inner.utf8_expected > 0 {
    raise ParseError::InvalidUtf8(
      pos=self.inner.utf8_start,
      kind=Utf8ErrorKind::InvalidContinuation,
    )
  }
  match self.inner.lex {
    LexNum =>
      if self.num_is_terminable() {
        self.finalize_number()
      } else {
        return FinishResult::Incomplete(
          pos=self.inner.offset,
          expected="数字尚未写完",
        )
      }
    LexNormal => ()
    LexStr =>
      return FinishResult::Incomplete(
        pos=self.inner.offset,
        expected="字符串缺少结束引号",
      )
    LexStrEscape =>
      return FinishResult::Incomplete(
        pos=self.inner.offset,
        expected="转义序列未完成",
      )
    LexStrHex(_, _) =>
      return FinishResult::Incomplete(
        pos=self.inner.offset,
        expected="\\u 转义未完成",
      )
    LexStrLowSlash(_) | LexStrLowU(_) | LexStrLowHex(_, _, _) =>
      return FinishResult::Incomplete(
        pos=self.inner.offset,
        expected="代理对未完成",
      )
    LexLit(_, _) =>
      return FinishResult::Incomplete(
        pos=self.inner.offset,
        expected="字面量未完成",
      )
  }
  match self.inner.ctx {
    RootDone => {
      let text = @utf8.decode(Bytes::from_array(self.inner.raw)) catch {
        _ =>
          raise ParseError::InvalidUtf8(
            pos=0,
            kind=Utf8ErrorKind::InvalidLeadByte,
          )
      }
      FinishResult::Completed(
        CompletedDocument::new(text, self.inner.total_bytes),
      )
    }
    RootStart =>
      FinishResult::Incomplete(
        pos=self.inner.offset,
        expected="文档尚未开始",
      )
    ObjKeyOrEnd =>
      FinishResult::Incomplete(
        pos=self.inner.offset,
        expected="对象键或 '}'",
      )
    ObjKey =>
      FinishResult::Incomplete(pos=self.inner.offset, expected="对象键")
    ObjColon => FinishResult::Incomplete(pos=self.inner.offset, expected="':'")
    ObjValue | ArrValue | ArrValueOrEnd =>
      FinishResult::Incomplete(pos=self.inner.offset, expected="值")
    ObjCommaOrEnd =>
      FinishResult::Incomplete(pos=self.inner.offset, expected="',' 或 '}'")
    ArrCommaOrEnd =>
      FinishResult::Incomplete(pos=self.inner.offset, expected="',' 或 ']'")
  }
}

///|
/// 当前值应该出现的路径。
fn Parser::value_path(self : Parser) -> Path {
  match self.inner.frames.last() {
    None => Path::root()
    Some(frame) =>
      match frame.kind {
        Obj => frame.pending_path
        Arr => frame.path.child_index(frame.count)
      }
  }
}

///|
/// 一个子值完成后,把父级上下文推进到 `,` 或结束。
fn Parser::after_child(self : Parser) -> Unit {
  match self.inner.frames.last() {
    None => self.inner.ctx = RootDone
    Some(frame) => {
      frame.count += 1
      self.inner.ctx = match frame.kind {
        Obj => ObjCommaOrEnd
        Arr => ArrCommaOrEnd
      }
    }
  }
}

///|
/// 记录 token 字节数并检查单 token 限制。
fn Parser::bump_token(self : Parser, pos : Int) -> Unit raise ParseError {
  self.inner.token_bytes += 1
  if self.inner.token_bytes > self.inner.limits.max_token_bytes {
    raise ParseError::LimitExceeded(
      kind=LimitKind::TokenBytes,
      pos~,
      allowed=self.inner.limits.max_token_bytes,
      actual=self.inner.token_bytes,
    )
  }
}

///|
/// 把本次 `feed` 累积的字符串增量交付出去。
fn Parser::flush_string_delta(self : Parser) -> Unit {
  if self.inner.lex is LexStr &&
    !self.inner.in_key &&
    !self.inner.str_delta.is_empty() {
    self.inner.events.push(
      Event::StringDelta(
        path=self.inner.cur_path,
        text=self.inner.str_delta.to_string(),
        span=Span::new(self.inner.token_start, self.inner.offset),
      ),
    )
    self.inner.str_delta.reset()
  }
}