///|
/// An HTTP method supported by the Mastodon-compatible REST API.
pub(all) enum HttpMethod {
  Get
  Post
  Put
  Patch
  Delete
} derive(Eq, Debug)

///|
#deprecated(skip_current_package=true)
#doc(hidden)
pub extend HttpMethod with Eq::{not_equal, equal}

///|
#deprecated(skip_current_package=true)
#doc(hidden)
pub extend HttpMethod with Debug::{to_repr}

///|
pub fn HttpMethod::to_string(self : Self) -> String {
  match self {
    Get => "GET"
    Post => "POST"
    Put => "PUT"
    Patch => "PATCH"
    Delete => "DELETE"
  }
}

///|
/// A fully encoded outbound request. Transports must not reinterpret `body`.
pub(all) struct HttpRequest {
  url : String
  http_method : HttpMethod
  headers : Map[String, String]
  body : Bytes
} derive(Eq, Debug)

///|
#deprecated(skip_current_package=true)
#doc(hidden)
pub extend HttpRequest with Eq::{not_equal, equal}

///|
#deprecated(skip_current_package=true)
#doc(hidden)
pub extend HttpRequest with Debug::{to_repr}

///|
pub fn HttpRequest::body_text(self : Self) -> String {
  @utf8.decode_lossy(self.body[:])
}

///|
pub fn HttpRequest::content_length(self : Self) -> Int32 {
  self.body.length()
}

///|
pub(all) struct HttpResponse {
  status : Int32
  /// Header names must be lower-cased by the transport.
  headers : Map[String, String]
  body : Bytes
} derive(Eq, Debug)

///|
#deprecated(skip_current_package=true)
#doc(hidden)
pub extend HttpResponse with Eq::{not_equal, equal}

///|
#deprecated(skip_current_package=true)
#doc(hidden)
pub extend HttpResponse with Debug::{to_repr}

///|
pub fn HttpResponse::header(self : Self, name : String) -> String? {
  self.headers.get(name.to_lower())
}

///|
pub fn HttpResponse::body_text(self : Self) -> String {
  @utf8.decode_lossy(self.body[:])
}

///|
/// The portable seam between request construction and an HTTP implementation.
/// Implementations should translate runtime/network failures to
/// `RequestFailed`; status-code interpretation stays in the portable core.
pub(open) trait Transport {
  async fn send(Self, HttpRequest) -> HttpResponse
  fn describe(Self) -> String
}