///|
pub(all) enum Tokenfast {
  IRI(Int, Int)
  Blank(Int, Int)
  Literal(Int, Int)
  Symbol(Byte, Int, Int)
  LineJump(Int, Int) // 换行位置
  EOF(Int) // 文件结束位置
  Error(Int, Int)
} derive(Debug)

///|
pub impl Show for Tokenfast with fn output(self : Tokenfast, logger : &Logger) -> Unit {
  match self {
    Tokenfast::IRI(start, end) => {
      logger.write_string("IRI")
      logger.write_string("(\{start}:\{end})")
    }
    Tokenfast::Blank(start, end) => {
      logger.write_string("Blank")
      logger.write_string("(\{start}:\{end})")
    }
    Tokenfast::Literal(start, end) => {
      logger.write_string("Literal")
      logger.write_string("(\{start}:\{end})")
    }
    Tokenfast::Symbol(_b, start, end) => {
      logger.write_string("Symbol")
      logger.write_string("(\{start}:\{end})")
    }
    Tokenfast::LineJump(start, end) => {
      logger.write_string("LineJump")
      logger.write_string("(\{start}:\{end})")
    }
    Tokenfast::EOF(start) => {
      logger.write_string("EOF")
      logger.write_string("(\{start})")
    }
    Tokenfast::Error(start, end) => {
      logger.write_string("Error")
      logger.write_string("(\{start}:\{end})")
    }
  }
}

///|
pub(all) struct Tokenizer {
  view : ArrayView[Byte]
  mut pos : Int
  mut len : Int
}

///|
pub fn Tokenizer::new(view : ArrayView[Byte]) -> Tokenizer {
  Tokenizer::{ view, pos: 0, len: view.length() }
}

///|
/// 跳过空白(空格、Tab、CR)
// fn Tokenizer::skip_whitespace(self : Tokenizer) -> Unit {
//   while self.pos < self.len {
//     match self.view[self.pos] {
//       b' ' | b'\t' | b'\r' => self.pos = self.pos + 1
//       _ => break
//     }
//   }
// }

///|
/// 跳过空白和注释
fn Tokenizer::skip_whitespace_and_comment(self : Tokenizer) -> Unit {
  while self.pos < self.len {
    match self.view[self.pos] {
      b' ' | b'\t' | b'\r' => self.pos = self.pos + 1
      b'#' => {
        // 跳过注释直到换行
        self.pos = self.pos + 1
        while self.pos < self.len && self.view[self.pos] != b'\n' {
          self.pos = self.pos + 1
        }
      }
      _ => break
    }
  }
}

///|
/// 消费指定字节,不匹配则报错
// fn Tokenizer::expect(self : Tokenizer, byte : Byte) -> Bool {
//   if self.pos < self.len && self.view[self.pos] == byte {
//     self.pos = self.pos + 1
//     true
//   } else {
//     false
//   }
// }

///|
/// 获取当前位置(用于错误报告)
pub fn Tokenizer::current_pos(self : Tokenizer) -> Int {
  self.pos
}

///|
/// 消费单字符符号
fn Tokenizer::consume_symbol(self : Tokenizer) -> Tokenfast {
  let start = self.pos
  let byte = self.view[self.pos]
  self.pos = self.pos + 1
  Tokenfast::Symbol(byte, start, self.pos)
}

///|
/// 解析满足条件的字符序列
fn Tokenizer::take_while(
  self : Tokenizer,
  predicate : (Byte) -> Bool,
) -> (Int, Int) {
  let start = self.pos
  while self.pos < self.len && predicate(self.view[self.pos]) {
    self.pos = self.pos + 1
  }
  (start, self.pos)
}

///|
/// 解析直到遇到指定字节(不含)
/// 返回 (start, end),end 是目标字节的位置
fn Tokenizer::take_until(self : Tokenizer, end_byte : Byte) -> (Int, Int)? {
  let start = self.pos
  while self.pos < self.len && self.view[self.pos] != end_byte {
    self.pos = self.pos + 1
  }

  if self.pos >= self.len {
    return None // 未找到目标字节
  }

  let end = self.pos
  self.pos = self.pos + 1 // 消费目标字节
  Some((start, end))
}

///|
/// 获取下一个 Tokenfast
fn Tokenizer::next(self : Tokenizer) -> Tokenfast? {
  // 跳过空白和注释
  self.skip_whitespace_and_comment()

  // 检查结束
  if self.pos >= self.len {
    return Some(Tokenfast::EOF(self.pos))
  }

  let start = self.pos
  let current = self.view[self.pos]

  match current {
    // IRI: <...>
    b'<' => {
      self.pos = self.pos + 1
      match self.take_until(b'>') {
        Some((iri_start, iri_end)) =>
          Some(Tokenfast::IRI(iri_start, iri_end + 1)) // 包含 >
        None => None // IRI 未闭合
      }
    }

    // 字面量: "..."
    b'"' => {
      self.pos = self.pos + 1
      match self.take_until(b'"') {
        Some((lit_start, lit_end)) =>
          Some(Tokenfast::Literal(lit_start, lit_end + 1)) // 包含 "
        None => None
      }
    }

    // Blank Node: _:name 或 :name
    b'_' | b':' => {
      self.pos = self.pos + 1
      // 跳过前缀后的 :
      if self.pos < self.len && self.view[self.pos] == b':' {
        self.pos = self.pos + 1
      }
      // 解析本地名
      let (name_start, name_end) = self.take_while(fn(b) {
        b.is_ascii_alnum() || b == b'_' || b == b'-'
      })
      if name_end > name_start {
        Some(Tokenfast::Blank(name_start - 2, name_end)) // 包含 _: 前缀
      } else {
        None // Blank Node 格式错误
      }
    }

    // 单字符符号
    b'.' | b',' | b';' | b'[' | b']' | b'(' | b')' | b'{' | b'}' | b'^' =>
      Some(self.consume_symbol())

    // 换行
    b'\n' => {
      self.pos = self.pos + 1
      Some(Tokenfast::LineJump(start, self.pos))
    }

    // 未知字符
    _ => None
  }
}

///|
/// 解析所有 Tokenfast
pub fn Tokenizer::tokenize(self : Tokenizer) -> Array[Tokenfast] {
  let tokens : Array[Tokenfast] = []

  while true {
    match self.next() {
      Some(token) => {
        tokens.push(token)
        if token.is_end() {
          break
        }
      }
      None => break // 解析错误,停止
    }
  }

  tokens
}

///|
fn Tokenfast::is_end(self : Tokenfast) -> Bool {
  match self {
    Tokenfast::EOF(_) => true
    _ => false
  }
}

///|
/// 从 Tokenfast 提取字符串
pub fn Tokenizer::extract(self : Tokenizer, start : Int, end : Int) -> String {
  let mut s = ""
  for i in start..)
pub fn Tokenizer::extract_iri(self : Tokenizer, token : Tokenfast) -> String {
  match token {
    Tokenfast::IRI(start, end) =>
      if end > start + 1 &&
        self.view[start] == b'<' &&
        self.view[end - 1] == b'>' {
        self.extract(start + 1, end - 1) // 去掉 <>
      } else {
        self.extract(start, end)
      }
    _ => ""
  }
}

///|
/// 预分配 tokens 数组减少扩容
pub fn Tokenizer::tokenize_with_capacity(
  self : Tokenizer,
  estimated_count : Int,
) -> Array[Tokenfast] {
  let tokens : Array[Tokenfast] = Array::make(
    estimated_count,
    Tokenfast::EOF(0),
  ) // 预分配

  while true {
    match self.next() {
      Some(token) => tokens.push(token)
      None => break
    }
  }
  tokens
}

///|
test "cursor tokenizer" {
  let input = "   .\n"
  let data = @utf8.encode(input).to_array()

  let tokenizer = Tokenizer::new(data[:])
  let tokens = tokenizer.tokenize()

  for token in tokens {
    match token {
      Tokenfast::IRI(start, end) =>
        debug("IRI: \{tokenizer.extract_iri(token)} at [\{start}:\{end}]")
      Tokenfast::Symbol(b, start, end) =>
        debug("Symbol: '\{b.to_char()}' at [\{start}:\{end}]")
      Tokenfast::LineJump(start, end) => debug("LineJump at [\{start}:\{end}]")
      Tokenfast::EOF(pos) => debug("EOF at \{pos}")
      _ => ()
    }
  }
}

///|
// test "benchmark: cursor tokenizer" {
//   let bench = @bench.Bench()

//   bench.bench(name="tokenize 1000 quads", fn() {
//     let n = 1000
//     let base = "http://example.org/"

//     let input = {
//       let mut s = ""
//       for i = 0; i < n; i = i + 1 {
//         s = s + "<\{base}s\{i}> <\{base}p\{i}> <\{base}o\{i}> .\n"
//       }
//       s
//     }

//     let bytes = @utf8.encode(input).to_array()[:]

//     let tokenizer = Tokenizer::new(bytes[:])
//     let tokens = tokenizer.tokenize()

//     // 统计 token 数量(验证解析正确性)
//     let mut iri_count = 0
//     let mut symbol_count = 0

//     for token in tokens {
//       match token {
//         Tokenfast::IRI(_, _) => iri_count = iri_count + 1
//         Tokenfast::Symbol(_, _, _) => symbol_count = symbol_count + 1
//         _ => ()
//       }
//     }

//     // 验证:每条 quad 有 3 个 IRI + 1 个 . = 4 tokens
//     // 1000 条 quad = 4000 IRI/Symbol + 1000 LineJump + 1 EOF
//     // assert!(iri_count >= 3000) // 确保解析正确
//   })

//   let summary = bench.dump_summaries()
//   debug(summary)
// }

///|
test "benchmark: tokenizer 1000 quad" {
  let n = 1000
  let base = "http://example.org/"

  let input = {
    let mut s = ""
    for i = 0; i < n; i = i + 1 {
      s = s + "<\{base}s\{i}> <\{base}p\{i}> <\{base}o\{i}> .\n"
    }
    s
  }

  let bytes = @utf8.encode(input).to_array()
  let start1 = @bench.monotonic_clock_start()

  // 词法解析
  let tokenizer = Tokenizer::new(bytes[:])
  let tokens = tokenizer.tokenize()
  let mut count = 0
  for token in tokens {
    match token {
      Tokenfast::IRI(_, _) => count = count + 1
      _ => ()
    }
  }

  let elapsed1 = @bench.monotonic_clock_end(start1)

  println("=== MoonBit 解析 test_1000.nq ===")
  println("")
  println("=== 性能数据 ===")
  println("Lexer:       \{elapsed1} µs (\{n} tokens)")
}