///|
/// Pure response plan. The caller remains responsible for HTTP policy and I/O.
pub(all) enum ResponsePlan {
  Ignore
  Unsatisfiable(Int64)
  Single(ConcreteRange)
  Multiple(Array[ConcreteRange])
} derive(Eq, Debug)

///|
pub fn plan_byte_range_response(
  request : RangeRequest,
  representation_length : Int64,
  method_is_get : Bool,
  range_supported : Bool,
  apply_ranges : Bool,
) -> Result[ResponsePlan, RangeError] {
  if !method_is_get ||
    !range_supported ||
    !apply_ranges ||
    !request.unit().is_bytes() {
    return Ok(Ignore)
  }
  let resolved = match resolve_byte_ranges(request, representation_length) {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  match resolved.ranges() {
    [] => Ok(Unsatisfiable(representation_length))
    [single] => Ok(Single(single))
    many => Ok(Multiple(many))
  }
}

///|
/// Suggested status assuming the caller applies this plan.
pub fn ResponsePlan::recommended_status(self : ResponsePlan) -> Int {
  match self {
    Ignore => 200
    Single(_) | Multiple(_) => 206
    Unsatisfiable(_) => 416
  }
}

///|
pub fn ResponsePlan::ranges(self : ResponsePlan) -> Array[ConcreteRange] {
  match self {
    Single(range) => [range]
    Multiple(ranges) => ranges.copy()
    _ => []
  }
}