///|
/// YAML Parser implementation
/// Simplified version based on js-yaml v3.13.1

// Parser state
struct ParserState {
  input : String
  mut position : Int
  mut line : Int
  mut column : Int
  length : Int
  options : ParseOptions
}

///|
fn ParserState::new(input : String, options : ParseOptions) -> ParserState {
  let sanitized_input = sanitize_input_internal(input)
  {
    input: sanitized_input,
    position: 0,
    line: 1,
    column: 1,
    length: sanitized_input.length(),
    options,
  }
}

///|
fn ParserState::current_char(self : ParserState) -> Int {
  if self.position >= self.length {
    0
  } else {
    self.input[self.position]
  }
}

///|
fn ParserState::peek_char(self : ParserState, offset : Int) -> Int {
  let pos = self.position + offset
  if pos >= self.length {
    0
  } else {
    self.input[pos]
  }
}

///|
fn ParserState::advance(self : ParserState) -> Unit {
  if self.position < self.length {
    let ch = self.current_char()
    self.position += 1
    if is_eol(ch) {
      self.line += 1
      self.column = 1
    } else {
      self.column += 1
    }
  }
}

///|
fn ParserState::skip_whitespace(self : ParserState) -> Unit {
  while is_whitespace_or_eol(self.current_char()) {
    self.advance()
  }
}

///|
fn ParserState::read_until(
  self : ParserState,
  predicate : (Int) -> Bool,
) -> String {
  let start = self.position
  while self.position < self.length && predicate(self.current_char()) {
    self.advance()
  }
  self.input.substring(start~, end=self.position)
}

///|
fn ParserState::error(self : ParserState, message : String) -> YamlParseError {
  YamlParseError(YamlError::ParseError(message, self.line, self.column))
}

///|
/// Sanitize input string for parsing (internal)
fn sanitize_input_internal(input : String) -> String {
  // Use the improved sanitize_input from utils
  let normalized = normalize_line_endings(input)
  sanitize_input(normalized)
}

///|
/// Parse a scalar value
fn parse_scalar(state : ParserState) -> YamlValue raise YamlParseError {
  state.skip_whitespace()
  if state.current_char() == 0 {
    return YamlValue::Null
  }
  let ch = state.current_char()

  // String literals
  if ch == DOUBLE_QUOTE {
    parse_double_quoted_string(state)
  } else if ch == SINGLE_QUOTE {
    parse_single_quoted_string(state)
  } else {
    parse_plain_scalar(state)
  }
}

///|
/// Parse double-quoted string
fn parse_double_quoted_string(
  state : ParserState,
) -> YamlValue raise YamlParseError {
  state.advance() // Skip opening quote
  let mut result = ""
  while state.current_char() != DOUBLE_QUOTE && state.current_char() != 0 {
    let ch = state.current_char()
    if ch == BACKSLASH {
      state.advance()
      let escaped = state.current_char()
      match escaped {
        0x22 => result += "\"" // " 
        0x5c => result += "\\" // \
        0x0a => result += "\n" // \n
        0x09 => result += "\t" // \t
        _ => {
          result += "\\"
          result += Char::from_int(escaped).to_string()
        }
      }
    } else {
      result += Char::from_int(ch).to_string()
    }
    state.advance()
  }
  if state.current_char() == DOUBLE_QUOTE {
    state.advance() // Skip closing quote
    YamlValue::String(result)
  } else {
    raise state.error("Unterminated quoted string")
  }
}

///|
/// Parse single-quoted string
fn parse_single_quoted_string(
  state : ParserState,
) -> YamlValue raise YamlParseError {
  state.advance() // Skip opening quote
  let mut result = ""
  while state.current_char() != SINGLE_QUOTE && state.current_char() != 0 {
    let ch = state.current_char()
    if ch == SINGLE_QUOTE && state.peek_char(1) == SINGLE_QUOTE {
      // Escaped single quote
      result += "'"
      state.advance()
      state.advance()
    } else {
      result += Char::from_int(ch).to_string()
      state.advance()
    }
  }
  if state.current_char() == SINGLE_QUOTE {
    state.advance() // Skip closing quote
    YamlValue::String(result)
  } else {
    raise state.error("Unterminated quoted string")
  }
}

///|
/// Parse plain scalar (unquoted)
fn parse_plain_scalar(state : ParserState) -> YamlValue {
  let text = state.read_until(fn(ch) {
    !is_whitespace_or_eol(ch) &&
    !is_flow_indicator(ch) &&
    ch != COLON &&
    ch != 0
  })
  if text.is_empty() {
    return YamlValue::Null
  }

  // Try to parse as number
  match parse_number(text) {
    Some(value) => value
    None =>
      // Check for boolean values
      match text.to_lower() {
        "true" | "yes" | "on" => YamlValue::Bool(true)
        "false" | "no" | "off" => YamlValue::Bool(false)
        "null" | "~" | "" => YamlValue::Null
        _ => YamlValue::String(text)
      }
  }
}

///|
/// Try to parse a string as a number
fn parse_number(text : String) -> YamlValue? {
  // Simple number parsing - this is a basic implementation
  // Try integer first - simple check for digits only
  if is_all_digits(text) {
    let i = parse_int_simple(text)
    Some(YamlValue::Int(i))
  } else if contains_dot(text) {
    // Try to parse as float
    let f = parse_double_simple(text)
    Some(YamlValue::Float(f))
  } else {
    None
  }
}

///|
/// Check if string contains only digits (and optional minus sign)
fn is_all_digits(text : String) -> Bool {
  if text.length() == 0 {
    return false
  }
  let start = if text[0] == 45 { 1 } else { 0 } // 45 is '-'
  if start >= text.length() {
    return false
  }
  for i = start; i < text.length(); i = i + 1 {
    let ch = text[i]
    if ch < 48 || ch > 57 { // 48-57 are '0'-'9'
      return false
    }
  }
  true
}

///|
/// Check if string contains a dot
fn contains_dot(text : String) -> Bool {
  for i = 0; i < text.length(); i = i + 1 {
    if text[i] == 46 { // 46 is '.'
      return true
    }
  }
  false
}

///|
/// Simple integer parsing
fn parse_int_simple(text : String) -> Int {
  let mut result = 0
  let mut negative = false
  let start = if text[0] == 45 { // 45 is '-'
    negative = true
    1
  } else {
    0
  }
  for i = start; i < text.length(); i = i + 1 {
    let digit = text[i] - 48 // Convert '0'-'9' to 0-9
    result = result * 10 + digit
  }
  if negative {
    -result
  } else {
    result
  }
}

///|
/// Simple double parsing - basic implementation
fn parse_double_simple(text : String) -> Double {
  // Very basic implementation - just convert to Int and then to Double for now
  // A full implementation would handle decimal points properly
  let parts = text.split(".")
  if parts.length() == 2 {
    let int_part = parse_int_simple(parts[0])
    let frac_part = parse_int_simple(parts[1])
    let divisor = power_of_10(parts[1].length())
    int_part.to_double() + frac_part.to_double() / divisor.to_double()
  } else {
    parse_int_simple(text).to_double()
  }
}

///|
/// Calculate 10^n
fn power_of_10(n : Int) -> Int {
  let mut result = 1
  for i = 0; i < n; i = i + 1 {
    result = result * 10
  }
  result
}

///|
/// Parse array (sequence)
fn parse_array(state : ParserState) -> YamlValue raise YamlParseError {
  state.advance() // Skip '['
  state.skip_whitespace()
  let result = []
  if state.current_char() == RIGHT_SQUARE_BRACKET {
    state.advance()
    return YamlValue::Array(result)
  }
  while true {
    let value = parse_value(state)
    result.push(value)
    state.skip_whitespace()
    let ch = state.current_char()
    if ch == RIGHT_SQUARE_BRACKET {
      state.advance()
      break
    } else if ch == COMMA {
      state.advance()
      state.skip_whitespace()
    } else if ch == 0 {
      raise state.error("Unterminated array")
    } else {
      raise state.error("Expected ',' or ']' in array")
    }
  }
  YamlValue::Array(result)
}

///|
/// Parse object (mapping)
fn parse_object(state : ParserState) -> YamlValue raise YamlParseError {
  state.advance() // Skip '{'
  state.skip_whitespace()
  let result = Map::new()
  if state.current_char() == RIGHT_CURLY_BRACKET {
    state.advance()
    return YamlValue::Object(result)
  }
  while true {
    // Parse key
    let key_value = parse_value(state)
    let key = match key_value {
      String(s) => s
      _ => raise state.error("Object key must be a string")
    }
    state.skip_whitespace()
    if state.current_char() != COLON {
      raise state.error("Expected ':' after object key")
    }
    state.advance() // Skip ':'
    state.skip_whitespace()

    // Parse value
    let value = parse_value(state)
    if !state.options.allow_duplicate_keys && result.contains(key) {
      raise state.error("Duplicate key: \{key}")
    }
    result.set(key, value)
    state.skip_whitespace()
    let ch = state.current_char()
    if ch == RIGHT_CURLY_BRACKET {
      state.advance()
      break
    } else if ch == COMMA {
      state.advance()
      state.skip_whitespace()
    } else if ch == 0 {
      raise state.error("Unterminated object")
    } else {
      raise state.error("Expected ',' or '}' in object")
    }
  }
  YamlValue::Object(result)
}

///|
/// Parse any YAML value
fn parse_value(state : ParserState) -> YamlValue raise YamlParseError {
  state.skip_whitespace()
  let ch = state.current_char()
  if ch == 0 {
    YamlValue::Null
  } else if ch == LEFT_SQUARE_BRACKET {
    parse_array(state)
  } else if ch == LEFT_CURLY_BRACKET {
    parse_object(state)
  } else {
    parse_scalar(state)
  }
}

///|
/// Check if current position is at a document separator
fn ParserState::is_at_document_separator(self : ParserState) -> Bool {
  self.current_char() == MINUS &&
  self.peek_char(1) == MINUS &&
  self.peek_char(2) == MINUS &&
  (self.peek_char(3) == 0 || is_whitespace_or_eol(self.peek_char(3)))
}

///|
/// Skip document separator (---)
fn ParserState::skip_document_separator(self : ParserState) -> Unit {
  if self.is_at_document_separator() {
    self.advance() // Skip first '-'
    self.advance() // Skip second '-'
    self.advance() // Skip third '-'
    self.skip_whitespace()
  }
}

///|
/// Read all documents from the input
fn ParserState::read_documents(
  self : ParserState,
) -> Array[YamlValue] raise YamlParseError {
  let documents = []
  self.skip_whitespace()

  // Handle initial document separator if present
  self.skip_document_separator()
  while self.current_char() != 0 {
    self.skip_whitespace()
    if self.current_char() == 0 {
      break
    }
    let document = parse_value(self)
    documents.push(document)
    self.skip_whitespace()
    if self.is_at_document_separator() {
      self.skip_document_separator()
    } else if self.current_char() != 0 {
      // If there's more content but no separator, it's an error
      break
    }
  }
  documents
}

///|
/// Parse a YAML string and return the parsed value
pub fn parse(
  content : String,
  options? : ParseOptions = ParseOptions::new(),
) -> YamlValue raise YamlParseError {
  let state = ParserState::new(content, options)

  // Use read_documents to get all documents
  let documents = state.read_documents()
  if documents.length() == 0 {
    YamlValue::Null
  } else if documents.length() == 1 {
    documents[0]
  } else {
    raise state.error(
      "Found more than 1 document in the stream: expected a single document",
    )
  }
}

///|
/// Parse multiple YAML documents from a single string
/// Returns an array of parsed documents
pub fn parse_all(
  content : String,
  options? : ParseOptions = ParseOptions::new(),
) -> Array[YamlValue] raise YamlParseError {
  let state = ParserState::new(content, options)
  state.read_documents()
}