/// The two dated text formats that are not RFC 3339: HTTP and ASN.1.
///
/// Every protocol invents its own way to spell a date, and then keeps the old
/// spellings working forever. These two families are the ones you meet while
/// speaking to a server or reading a certificate.
///
///     moon run src/examples/wire

///|
/// Parse an ASN.1 time and report either the reading or the refusal, so the
/// table below stays one line per case.
fn asn1_error(text : String) -> String {
  try {
    let moment = @moondate.asn1(text)
    "accepted as " + moment.to_string()
  } catch {
    err => err.to_string()
  }
}

///|
fn http_error(text : String) -> String {
  try {
    let moment = @moondate.http(text)
    "accepted as " + moment.to_string()
  } catch {
    err => err.to_string()
  }
}

///|
fn main raise {
  // ---- HTTP ---------------------------------------------------------------
  //
  // RFC 9110 asks a recipient to accept three formats. The first is the one to
  // send; the other two are the ones you must still read.

  let imf = @moondate.http("Sun, 06 Nov 1994 08:49:37 GMT") // the one to send
  let rfc850 = @moondate.http("Sunday, 06-Nov-94 08:49:37 GMT") // obsolete
  let asctime = @moondate.http("Sun Nov  6 08:49:37 1994") // obsolete

  println(imf)
  println(rfc850)
  println(asctime)
  println(
    "all three are the same instant: " +
    (imf.epoch() == asctime.epoch()).to_string(),
  )
  println("")

  // Writing goes back out in the preferred form, whatever shape the moment has —
  // as long as it can name an instant at all.
  println(imf.http_text())
  println(rfc850.http_text())
  println("")

  // A two-digit year in an HTTP date is not the same rule as the one in ASN.1.
  // RFC 6265 says 69 and under mean the 2000s, so this is 2069, not 1969. The
  // two-digit form only appears in the obsolete RFC 850 spelling.
  let cookie_year = @moondate.http("Sunday, 06-Nov-69 08:49:37 GMT")
  println("2069 or 1969? " + cookie_year.to_string())
  println("")

  // ---- ASN.1 --------------------------------------------------------------
  //
  // Certificates carry their validity in UTCTime or GeneralizedTime. UTCTime
  // drops the century; RFC 5280 fills it back in with 50 as the pivot, which is
  // the opposite of HTTP's 70.

  let utc_time = @moondate.asn1("260922143000Z") // UTCTime, DER form
  let generalized = @moondate.asn1("20260922143000Z") // GeneralizedTime

  println(utc_time)
  println(generalized)
  println(
    "both parse to the same instant: " +
    (utc_time.epoch() == generalized.epoch()).to_string(),
  )
  println("")

  // The pivot, both ways. 49 is 2049; 50 is 1950.
  println(@moondate.asn1("491231235959Z").to_string())
  println(@moondate.asn1("500101000000Z").to_string())
  println("")

  // Writing always uses GeneralizedTime: it spells the century out, so nothing
  // has to be guessed on the way back in.
  println(@moondate.parse("2026-09-22T14:30:00Z").asn1_text())
  println(@moondate.parse("2049-12-31T23:59:59Z").asn1_text())
  println(@moondate.parse("2050-01-01T00:00:00Z").asn1_text())
  println("")

  // ---- refusals -----------------------------------------------------------
  //
  // Neither reader guesses. A short field, a missing `Z`, or a letter where a
  // digit belongs comes back as an error with the reason inside it.

  let asn1_attempts = [
    "260922143000A", // right length, but DER requires the Z
     "2609221430", // truncated
     "2026-09-22", // RFC 3339, not ASN.1
  ]
  for text in asn1_attempts {
    println(text + " -> " + asn1_error(text))
  }
  println("")

  let http_attempts = [
    "Sun, 06 Nov 1994", // the day without the clock
     "Sun Nov  6 08:49:37", // asctime with the year cut off
     "yesterday", // not a date at all
  ]
  for text in http_attempts {
    println(text + " -> " + http_error(text))
  }
}