#ifndef _TILE_NET_HTTP_TYPES_H
#define _TILE_NET_HTTP_TYPES_H

#pragma once

#include "tile/base/optional.h"
#include "tile/base/string.h"

namespace tile {
enum class HttpVersion { Unspecified, V_1_0, V_1_1, V_2, V_3 };

enum class HttpMethod { Unspecified, Head, Get, Post, Put, Delete, Options, Trace, Connect, Patch };

// @sa: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
enum class HttpStatus {// `HttpStatusCode`?
    Continue                      = 100,
    SwitchingProtocols            = 101,
    EarlyHints                    = 103,
    OK                            = 200,
    Created                       = 201,
    Accepted                      = 202,
    NonAuthoritativeInformation   = 203,
    NoContent                     = 204,
    ResetContent                  = 205,
    PartialContent                = 206,
    MultipleChoices               = 300,
    MovedPermanently              = 301,
    Found                         = 302,
    SeeOther                      = 303,
    NotModified                   = 304,
    TemporaryRedirect             = 307,
    PermanentRedirect             = 308,
    BadRequest                    = 400,
    Unauthorized                  = 401,
    PaymentRequired               = 402,
    Forbidden                     = 403,
    NotFound                      = 404,
    MethodNotAllowed              = 405,
    NotAcceptable                 = 406,
    ProxyAuthenticationRequired   = 407,
    RequestTimeout                = 408,
    Conflict                      = 409,
    Gone                          = 410,
    LengthRequired                = 411,
    PreconditionFailed            = 412,
    PayloadTooLarge               = 413,
    URITooLong                    = 414,
    UnsupportedMediaType          = 415,
    RangeNotSatisfiable           = 416,
    ExpectationFailed             = 417,
    ImATeapot                     = 418,// No you're not.
    UnprocessableEntity           = 422,
    TooEarly                      = 425,
    UpgradeRequired               = 426,
    PreconditionRequired          = 428,
    TooManyRequests               = 429,
    RequestHeaderFieldsTooLarge   = 431,
    UnavailableForLegalReasons    = 451,
    InternalServerError           = 500,
    NotImplemented                = 501,
    BadGateway                    = 502,
    ServiceUnavailable            = 503,
    GatewayTimeout                = 504,
    HTTPVersionNotSupported       = 505,
    VariantAlsoNegotiates         = 506,
    InsufficientStorage           = 507,
    LoopDetected                  = 508,
    NotExtended                   = 510,
    NetworkAuthenticationRequired = 511
};

// AllHttpStatus for for_each
static HttpStatus AllHttpStatus[] = {
    HttpStatus::Continue,
    HttpStatus::SwitchingProtocols,
    HttpStatus::EarlyHints,
    HttpStatus::OK,
    HttpStatus::Created,
    HttpStatus::Accepted,
    HttpStatus::NonAuthoritativeInformation,
    HttpStatus::NoContent,
    HttpStatus::ResetContent,
    HttpStatus::PartialContent,
    HttpStatus::MultipleChoices,
    HttpStatus::MovedPermanently,
    HttpStatus::Found,
    HttpStatus::SeeOther,
    HttpStatus::NotModified,
    HttpStatus::TemporaryRedirect,
    HttpStatus::PermanentRedirect,
    HttpStatus::BadRequest,
};

Slice ToSlice(HttpVersion method) noexcept;
Slice ToSlice(HttpMethod) noexcept;
Slice ToSlice(HttpStatus status) noexcept;

template<>
struct TryParseTraits<HttpMethod> {
    static std::optional<HttpMethod> TryParse(Slice s);
};

template<>
struct TryParseTraits<HttpVersion> {
    static std::optional<HttpVersion> TryParse(Slice s);
};

std::ostream &operator<<(std::ostream &os, HttpMethod method);
std::ostream &operator<<(std::ostream &os, HttpStatus status);
std::ostream &operator<<(std::ostream &os, HttpVersion version);

}// namespace tile

#endif// _TILE_NET_HTTP_TYPES_H
