///|
pub(all) struct SearchEntry {
  title : String
  route : String
  description : String
  text : String
}

///|
pub fn build_search_index(
  pages : Array[PagePlan],
  sources : Array[PageSource],
) -> String {
  let mut json = "["
  let mut first = true
  for page in pages {
    if first {
      first = false
    } else {
      json = json + ","
    }
    json = json +
      search_entry_json({
        title: page.title,
        route: page.route,
        description: page.description,
        text: compact_text(source_for_path(sources, page.source_path)),
      })
  }
  json + "]"
}

///|
pub fn search_entry_json(entry : SearchEntry) -> String {
  "{" +
  "\"title\":\"" +
  escape_json(entry.title) +
  "\"," +
  "\"route\":\"" +
  escape_json(entry.route) +
  "\"," +
  "\"description\":\"" +
  escape_json(entry.description) +
  "\"," +
  "\"text\":\"" +
  escape_json(entry.text) +
  "\"" +
  "}"
}

///|
pub fn compact_text(input : String) -> String {
  let mut text = ""
  let body = strip_front_matter(input)
  for line in body.split("\n") {
    let cleaned = line.trim().to_owned()
    if cleaned != "" {
      if text != "" {
        text = text + " "
      }
      text = text + cleaned
    }
  }
  text
}

///|
pub fn escape_json(input : String) -> String {
  input
  .replace_all(old="\\", new="\\\\")
  .replace_all(old="\"", new="\\\"")
  .replace_all(old="\n", new="\\n")
  .replace_all(old="\r", new="\\r")
  .replace_all(old="\t", new="\\t")
}

///|
fn source_for_path(sources : Array[PageSource], path : String) -> String {
  for source in sources {
    if source.path == path {
      return source.source
    }
  }
  ""
}