///|
/// JSON input bridge for the local HTTP integration harness.
struct Input {
  http_method : String
  status : Int
  retry_index : Int
  elapsed_ms : Int
  body_replayable : Bool
  replay_safe : Bool
  headers : Array[String]
  now_seconds : Int
  sample_ppm : Int
  max_retries : Int
  base_delay_ms : Int
  max_delay_ms : Int
  total_budget_ms : Int
  request_reserve_ms : Int
} derive(FromJson)

///|
fn main {
  let args = @env.args()
  let input : Input = @json.from_json(@json.parse(args[args.length() - 1])) catch {
    _ => abort("Expected a simulation request as the final JSON argument")
  }
  let settings : @retry.Settings = {
    max_retries: input.max_retries,
    base_delay_ms: input.base_delay_ms.to_int64(),
    max_delay_ms: input.max_delay_ms.to_int64(),
    total_budget_ms: input.total_budget_ms.to_int64(),
    request_reserve_ms: input.request_reserve_ms.to_int64(),
  }
  let decision = @retry.decide_response(
    settings,
    http_method=input.http_method,
    status=input.status,
    retry_index=input.retry_index,
    elapsed_ms=input.elapsed_ms.to_int64(),
    body_replayable=input.body_replayable,
    replay_safe=input.replay_safe,
    retry_after_values=input.headers,
    now_seconds=input.now_seconds.to_int64(),
    sample_ppm=input.sample_ppm,
  )
  match decision {
    Wait(ms) => println("WAIT \{ms}")
    Stop(reason) => {
      let name = match reason {
        InvalidSettings => "InvalidSettings"
        InvalidInput => "InvalidInput"
        NotRetryable => "NotRetryable"
        NotReplayable => "NotReplayable"
        AttemptsExhausted => "AttemptsExhausted"
        BudgetExhausted => "BudgetExhausted"
        ServerDelayExceedsCap => "ServerDelayExceedsCap"
        InvalidRetryAfter => "InvalidRetryAfter"
      }
      println("STOP \{name}")
    }
  }
}