///|
pub struct SliceParser {
  engine : NQuadsEngine
  data : ArrayView[Byte]
  lenient : Bool // lenient 模式下跳过验证
  errors : Array[ParseError] // 收集的结构错误
}

///|
pub fn SliceParser::new(
  engine : NQuadsEngine,
  data : ArrayView[Byte],
  lenient? : Bool = false,
) -> SliceParser {
  { engine, data, lenient, errors: [] }
}

///|
/// 链式调用设置宽松模式
pub fn SliceParser::lenient(self : SliceParser) -> SliceParser {
  { ..self, lenient: true }
}

///|
/// 实现 Iter trait

///|
pub fn SliceParser::next(self : SliceParser) -> Result[QuadSpan, ParseError]? {
  match self.engine.next() {
    None => {
      // 检查最后是否有未处理的错误
      match self.engine.last_error {
        Some((span, line)) =>
          self.errors.push(
            ParseError::StructSyntaxErr("Structure error", line, span),
          )
        None => ()
      }
      None
    }
    Some(Err(e)) => Some(Err(e))
    Some(Ok(pending)) =>
      match self.validate(pending) {
        Ok(q) => Some(Ok(q))
        Err(e) => {
          self.errors.push(e)
          self.next() // 递归重试
        }
      }
  }
}

///|
/// 解析全部
pub fn SliceParser::parse_all(
  self : SliceParser,
) -> (Array[QuadSpan], Array[ParseError]) {
  let quads : Array[QuadSpan] = []
  let errors = self.errors

  for ;; {
    match self.next() {
      Some(Ok(q)) => quads.push(q)
      Some(Err(_e)) => continue
      None => break
    }
  }

  (quads, errors)
}

///|
fn SliceParser::validate(
  self : SliceParser,
  pending : PendingQuad,
) -> Result[QuadSpan, ParseError] {
  // 提取 span 并切分 data
  let (subj_off, subj_len) = pending.subj
  let (pred_off, pred_len) = pending.pred
  let (obj_off, obj_len) = pending.obj

  // 边界检查
  if subj_off < 0 || subj_off + subj_len > self.data.length() {
    return Err(ParseError::SyntaxErr("Invalid subject span", pending.subj))
  }
  if pred_off < 0 || pred_off + pred_len > self.data.length() {
    return Err(ParseError::SyntaxErr("Invalid predicate span", pending.pred))
  }
  if obj_off < 0 || obj_off + obj_len > self.data.length() {
    return Err(ParseError::SyntaxErr("Invalid object span", pending.obj))
  }

  let subject = self.data[subj_off:subj_off + subj_len]
  let predicate = self.data[pred_off:pred_off + pred_len]
  let object = self.data[obj_off:obj_off + obj_len]

  // 检测主语和宾语的类型
  let subj_type = if subject[0] == b'_' {
    TermType::BNode
  } else {
    TermType::Iri
  }

  let obj_type = if object[0] == b'_' {
    TermType::BNode
  } else if object[0] == b'"' {
    TermType::Literal
  } else {
    TermType::Iri
  }
  // 严格模式:验证 IRI 格式
  if !self.lenient {
    // 验证 IRI
    if subj_type == TermType::Iri {
      match validate_iri(subject) {
        Ok(_) => ()
        Err(e) => return Err(e)
      }
    }
    if obj_type == TermType::Iri {
      match validate_iri(object) {
        Ok(_) => ()
        Err(e) => return Err(e)
      }
    }
    // 验证 BlankNode
    if subj_type == TermType::BNode {
      match validate_bnode(subject) {
        Ok(_) => ()
        Err(e) => return Err(e)
      }
    }
    if obj_type == TermType::BNode {
      match validate_bnode(object) {
        Ok(_) => ()
        Err(e) => return Err(e)
      }
    }
  }
  // 图名

  let (g_off, g_len) = pending.graph
  if g_len > 0 {
    if g_off < 0 || g_off + g_len > self.data.length() {
      return Err(ParseError::SyntaxErr("Invalid graph span", pending.graph))
    }
  }
  let graph = if g_len > 0 {
    Some(self.data[g_off:g_off + g_len])
  } else {
    None
  }

  Ok({ subj: subject, pred: predicate, obj: object, graph, subj_type, obj_type })
}

///|
/// IRI 验证
fn validate_iri(iri : ArrayView[Byte]) -> Result[Unit, ParseError] {
  let len = iri.length()

  if len < 2 || iri[0] != b'<' || iri[len - 1] != b'>' {
    return Err(ParseError::SyntaxErr("IRI must be wrapped in <>", (0, len)))
  }

  if len == 2 {
    return Err(ParseError::SyntaxErr("IRI cannot be empty", (0, len)))
  }

  // 可选:验证协议
  let inner = iri[1:len - 1]
  let first = inner[0]

  if !(first == b'h' || first == b'f' || first == b'm' || first == b'/') {
    return Err(
      ParseError::SyntaxErr(
        "IRI must start with http://, https://, or ftp://",
        (1, inner.length()),
      ),
    )
  }

  Ok(())
}

///|
/// BNode 验证
fn validate_bnode(bnode : ArrayView[Byte]) -> Result[Unit, ParseError] {
  let len = bnode.length()

  if len < 3 || bnode[0] != b'_' || bnode[1] != b':' {
    return Err(ParseError::SyntaxErr("Blank node must start with _:", (0, len)))
  }

  let first = bnode[2]
  if !((first >= b'a' && first <= b'z') ||
    (first >= b'A' && first <= b'Z') ||
    first == b'_') {
    return Err(
      ParseError::SyntaxErr(
        "Blank node label must start with letter or underscore",
        (2, 1),
      ),
    )
  }

  Ok(())
}