///|
pub(all) struct Landing {
  id : String
  description : String
  search : String?
  collections : String?
  conforms_to : Array[String]
} derive(Debug, Eq)

///|
pub fn parse_landing(text : String) -> Landing raise StacError {
  let v = @json.parse(text) catch { _ => raise Invalid("invalid JSON") }
  let version = string_field(v, "stac_version")
  if version != "1.0.0" && version != "1.1.0" {
    raise Invalid("unsupported stac_version")
  }
  if string_field(v, "type") != "Catalog" {
    raise Invalid("expected Catalog")
  }
  let id = string_field(v, "id")
  let description = string_field(v, "description")
  ignore(validate_links(v, "landing"))
  let links = match field(v, "links") {
    Some(Array(xs)) => xs
    _ => raise Invalid("invalid links")
  }
  let mut search : String? = None
  let mut collections : String? = None
  for link in links {
    let rel = string_field(link, "rel")
    if rel == "search" && search == None {
      search = Some(string_field(link, "href"))
    }
    if rel == "data" && collections == None {
      collections = Some(string_field(link, "href"))
    }
  }
  let conforms_to : Array[String] = []
  match field(v, "conformsTo") {
    None => ()
    Some(Array(values)) =>
      for value in values {
        match value {
          String(uri) if uri != "" => conforms_to.push(uri)
          _ => raise Invalid("invalid conformsTo")
        }
      }
    _ => raise Invalid("invalid conformsTo")
  }
  { id, description, search, collections, conforms_to }
}

///|
pub fn landing_summary(input : String) -> String {
  landing_summary_checked(input) catch {
    Invalid(message) => error_json(message)
  }
}

///|
fn landing_summary_checked(input : String) -> String raise StacError {
  let landing = parse_landing(input)
  let conforms : Array[Json] = []
  for uri in landing.conforms_to {
    conforms.push(Json::string(uri))
  }
  let output : Json = {
    "status": "ok",
    "id": landing.id,
    "description": landing.description,
    "search": match landing.search {
      Some(uri) => Json::string(uri)
      None => Json::null()
    },
    "collections": match landing.collections {
      Some(uri) => Json::string(uri)
      None => Json::null()
    },
    "conformsTo": Json::array(conforms),
  }
  output.stringify()
}