///|
pub struct Directive {
  line : Int
  key : String
  value : String
  raw : String
} derive(Debug, Eq)

///|
pub fn directives(text : String) -> Array[Directive] {
  let result : Array[Directive] = []
  let mut line_no = 0
  for raw in split_lines(text) {
    line_no += 1
    let line = trim_ascii(strip_inline_comment(raw))
    if line == "" {
      continue
    }
    let parts = split_once(line, ":")
    if parts.length() >= 2 {
      result.push({
        line: line_no,
        key: lower_ascii(trim_ascii(parts[0])),
        value: trim_ascii(parts[1]),
        raw,
      })
    } else {
      result.push({ line: line_no, key: "", value: "", raw })
    }
  }
  result
}

///|
pub fn directives_for_key(text : String, key : String) -> Array[Directive] {
  let result : Array[Directive] = []
  let needle = lower_ascii(key)
  for item in directives(text) {
    if item.key == needle {
      result.push(item)
    }
  }
  result
}

///|
pub fn directive_values(text : String, key : String) -> Array[String] {
  let result : Array[String] = []
  for item in directives_for_key(text, key) {
    result.push(item.value)
  }
  result
}

///|
pub fn unknown_directives(text : String) -> Array[Directive] {
  let result : Array[Directive] = []
  for item in directives(text) {
    if item.key != "" && !known_directive(item.key) {
      result.push(item)
    }
  }
  result
}

///|
pub fn known_directive(key : String) -> Bool {
  key == "user-agent" ||
  key == "allow" ||
  key == "disallow" ||
  key == "crawl-delay" ||
  key == "sitemap" ||
  key == "host"
}

///|
pub fn directive_report(text : String) -> String {
  let rows : Array[String] = []
  for item in directives(text) {
    rows.push(item.line.to_string() + " " + item.key + "=" + item.value)
  }
  join_lines(rows)
}

///|
pub fn directive_count(text : String, key : String) -> Int {
  directives_for_key(text, key).length()
}

///|
pub fn first_directive_value(text : String, key : String) -> String? {
  let values = directive_values(text, key)
  if values.is_empty() {
    None
  } else {
    Some(values[0])
  }
}