///|
/// The error type raised by every fallible Temporal operation.
///
/// The variants mirror the ECMAScript exception that a JavaScript engine would
/// surface for the same failure, which is what `temporal_rs` models with its
/// `ErrorKind`. Keeping that distinction lets an engine embedding this library
/// map a failure onto the right JavaScript error constructor.
pub(all) suberror TemporalError {
  /// A plain `Error`.
  Generic(String)
  /// A `TypeError`: a value had the wrong shape or type.
  TypeError(String)
  /// A `RangeError`: a value was outside its permitted range. This is by far
  /// the most common Temporal failure.
  RangeError(String)
  /// A `SyntaxError`: a string could not be parsed.
  SyntaxError(String)
  /// An internal invariant was violated. Reaching this is a bug in the port.
  AssertError(String)
} derive(Eq)

///|
pub impl Show for TemporalError with fn output(self, logger) {
  logger.write_string(self.kind_name())
  logger.write_string(": ")
  logger.write_string(self.message())
}

///|
pub impl Debug for TemporalError with fn to_repr(self) {
  Repr::Repr(self.to_string())
}

///|
/// Returns the ECMAScript error constructor name for this failure.
pub fn TemporalError::kind_name(self : TemporalError) -> String {
  match self {
    Generic(_) => "Error"
    TypeError(_) => "TypeError"
    RangeError(_) => "RangeError"
    SyntaxError(_) => "SyntaxError"
    AssertError(_) => "ImplementationError"
  }
}

///|
/// Returns the human-readable description of the failure.
pub fn TemporalError::message(self : TemporalError) -> String {
  match self {
    Generic(m)
    | TypeError(m)
    | RangeError(m)
    | SyntaxError(m)
    | AssertError(m) => m
  }
}

///|
/// Unwraps a value the caller believes is always present, raising an
/// `AssertError` when it is not.
///
/// This is the port's counterpart to `temporal_rs`'s `TemporalUnwrap`.
fn[T] temporal_unwrap(value : T?, context : String) -> T raise TemporalError {
  match value {
    Some(v) => v
    None => raise AssertError("unexpected empty value: \{context}")
  }
}