`%||%` <- function(x, y) if (is.null(x)) y else x

gv <- function(x) {
  tryCatch(
    httpcode::http_code(x, TRUE)$verbose_explanation,
    error = function(e) NULL
  ) %||%
    ""
}


error_child_generator <- function(class_name, x) {
  self <- super <- NULL
  R6::R6Class(
    class_name,
    inherit = Error,
    public = list(
      name = class_name,
      status_code = x,
      mssg = gv(x),

      do_verbose = function(
        response,
        template = self$message_template_verbose
      ) {
        super$do(response, self$mssg, template)
      }
    )
  )
}


#' Individual error classes
#'
#' These error classes are for each HTTP error, and inherit from
#' the [Error] class in this package.
#'
#' @details In addition to what's available in [Error],
#' these classes have a single variable `mssg` that is the very
#' verbose complete message describing the HTTP condition in detail.
#' You can include that message in your condition by using `do_verbose`
#' (see below)
#'
#' @section Methods:
#'
#' In addition to the methods documented in [Error], these classes
#' also have:
#'
#' * `do_verbose(response, template)`:
#'
#'   Execute condition, whether it be message, warning, or error.
#'
#'   * response: is any response from `crul`, `curl`, or `httr`
#'   Execute condition, whether it be message, warning, error, or your
#'   own custom function. This method uses `message_template_verbose`,
#'   and uses it's default value.
#'   * template: a template to use for the verbose message, see [Error]
#'   for details
#'
#' @seealso [fauxpas::Error], [fauxpas::http]
#'
#' @examples
#' HTTPRequestURITooLong$new(
#'   message_template = "{{reason}} ............ {{status}}",
#'   message_template_verbose = "{{reason}} .>.>.>.>.>.> {{status}}\n {{message}}"
#' )
#' @format NULL
#' @usage NULL
#' @name Error-Classes
NULL


# 100 ----------------------
#' @export
#' @rdname Error-Classes
HTTPContinue <- error_child_generator("HTTPContinue", 100)

#' @export
#' @rdname Error-Classes
HTTPSwitchProtocol <- error_child_generator("HTTPSwitchProtocol", 101)

#' @export
#' @rdname Error-Classes
HTTPProcessing <- error_child_generator("HTTPProcessing", 102)


# 200 ----------------------
#' @export
#' @rdname Error-Classes
HTTPOK <- error_child_generator("HTTPOK", 200)

#' @export
#' @rdname Error-Classes
HTTPCreated <- error_child_generator("HTTPCreated", 201)

#' @export
#' @rdname Error-Classes
HTTPAccepted <- error_child_generator("HTTPAccepted", 202)

#' @export
#' @rdname Error-Classes
HTTPNonAuthoritativeInformation <- error_child_generator(
  "HTTPNonAuthoritativeInformation",
  203
)

#' @export
#' @rdname Error-Classes
HTTPNoContent <- error_child_generator("HTTPNoContent", 204)

#' @export
#' @rdname Error-Classes
HTTPResetContent <- error_child_generator("HTTPResetContent", 205)

#' @export
#' @rdname Error-Classes
HTTPPartialContent <- error_child_generator("HTTPPartialContent", 206)

#' @export
#' @rdname Error-Classes
HTTPMultiStatus <- error_child_generator("HTTPMultiStatus", 207)

#' @export
#' @rdname Error-Classes
HTTPAlreadyReported <- error_child_generator("HTTPAlreadyReported", 208)

#' @export
#' @rdname Error-Classes
HTTPImUsed <- error_child_generator("HTTPImUsed", 226)


# 300 ----------------------
#' @export
#' @rdname Error-Classes
HTTPMultipleChoices <- error_child_generator("HTTPMultipleChoices", 300)

#' @export
#' @rdname Error-Classes
HTTPMovedPermanently <- error_child_generator("HTTPMovedPermanently", 301)

#' @export
#' @rdname Error-Classes
HTTPFound <- error_child_generator("HTTPFound", 302)

#' @export
#' @rdname Error-Classes
HTTPSeeOther <- error_child_generator("HTTPSeeOther", 303)

#' @export
#' @rdname Error-Classes
HTTPNotModified <- error_child_generator("HTTPNotModified", 304)

#' @export
#' @rdname Error-Classes
HTTPUseProxy <- error_child_generator("HTTPUseProxy", 305)

#' @export
#' @rdname Error-Classes
HTTPSwitchProxy <- error_child_generator("HTTPSwitchProxy", 306)

#' @export
#' @rdname Error-Classes
HTTPTemporaryRedirect <- error_child_generator("HTTPTemporaryRedirect", 307)

#' @export
#' @rdname Error-Classes
HTTPPermanentRedirect <- error_child_generator("HTTPPermanentRedirect", 308)


# 400 ----------------------
#' @export
#' @rdname Error-Classes
HTTPBadRequest <- error_child_generator("HTTPBadRequest", 400)

#' @export
#' @rdname Error-Classes
HTTPUnauthorized <- error_child_generator("HTTPUnauthorized", 401)

#' @export
#' @rdname Error-Classes
HTTPPaymentRequired <- error_child_generator("HTTPPaymentRequired", 402)

#' @export
#' @rdname Error-Classes
HTTPForbidden <- error_child_generator("HTTPForbidden", 403)

#' @export
#' @rdname Error-Classes
HTTPNotFound <- error_child_generator("HTTPNotFound", 404)

#' @export
#' @rdname Error-Classes
HTTPMethodNotAllowed <- error_child_generator("HTTPMethodNotAllowed", 405)

#' @export
#' @rdname Error-Classes
HTTPNotAcceptable <- error_child_generator("HTTPNotAcceptable", 406)

#' @export
#' @rdname Error-Classes
HTTPProxyAuthenticationRequired <- error_child_generator(
  "HTTPProxyAuthenticationRequired",
  407
)

#' @export
#' @rdname Error-Classes
HTTPRequestTimeout <- error_child_generator("HTTPRequestTimeout", 408)

#' @export
#' @rdname Error-Classes
HTTPConflict <- error_child_generator("HTTPConflict", 409)

#' @export
#' @rdname Error-Classes
HTTPGone <- error_child_generator("HTTPGone", 410)

#' @export
#' @rdname Error-Classes
HTTPLengthRequired <- error_child_generator("HTTPLengthRequired", 411)

#' @export
#' @rdname Error-Classes
HTTPPreconditionFailed <- error_child_generator("HTTPPreconditionFailed", 412)

#' @export
#' @rdname Error-Classes
HTTPRequestEntityTooLarge <- error_child_generator(
  "HTTPRequestEntityTooLarge",
  413
)

#' @export
#' @rdname Error-Classes
HTTPRequestURITooLong <- error_child_generator("HTTPRequestURITooLong", 414)

#' @export
#' @rdname Error-Classes
HTTPUnsupportedMediaType <- error_child_generator(
  "HTTPUnsupportedMediaType",
  415
)

#' @export
#' @rdname Error-Classes
HTTPRequestRangeNotSatisfiable <- error_child_generator(
  "HTTPRequestRangeNotSatisfiable",
  416
)

#' @export
#' @rdname Error-Classes
HTTPExpectationFailed <- error_child_generator("HTTPExpectationFailed", 417)

#' @export
#' @rdname Error-Classes
HTTPTeaPot <- error_child_generator("HTTPTeaPot", 418)

#' @export
#' @rdname Error-Classes
HTTPAuthenticationTimeout <- error_child_generator(
  "HTTPAuthenticationTimeout",
  419
)

#' @export
#' @rdname Error-Classes
HTTPMethodFailure <- error_child_generator("HTTPMethodFailure", 420)

#' @export
#' @rdname Error-Classes
HTTPMisdirectedRequest <- error_child_generator("HTTPMisdirectedRequest", 421)

#' @export
#' @rdname Error-Classes
HTTPUnprocessableEntity <- error_child_generator("HTTPUnprocessableEntity", 422)

#' @export
#' @rdname Error-Classes
HTTPLocked <- error_child_generator("HTTPLocked", 423)

#' @export
#' @rdname Error-Classes
HTTPFailedDependency <- error_child_generator("HTTPFailedDependency", 424)

#' @export
#' @rdname Error-Classes
HTTPUnorderedCollection <- error_child_generator("HTTPUnorderedCollection", 425)

#' @export
#' @rdname Error-Classes
HTTPUpgradeRequired <- error_child_generator("HTTPUpgradeRequired", 426)

#' @export
#' @rdname Error-Classes
HTTPPreconditionRequired <- error_child_generator(
  "HTTPPreconditionRequired",
  428
)

#' @export
#' @rdname Error-Classes
HTTPTooManyRequests <- error_child_generator("HTTPTooManyRequests", 429)

#' @export
#' @rdname Error-Classes
HTTPRequestHeaderFieldsTooLarge <- error_child_generator(
  "HTTPRequestHeaderFieldsTooLarge",
  431
)

#' @export
#' @rdname Error-Classes
HTTPLoginTimeout <- error_child_generator("HTTPLoginTimeout", 440)

#' @export
#' @rdname Error-Classes
HTTPNoResponse <- error_child_generator("HTTPNoResponse", 444)

#' @export
#' @rdname Error-Classes
HTTPRetryWith <- error_child_generator("HTTPRetryWith", 449)

#' @export
#' @rdname Error-Classes
HTTPBlockedByWindowsParentalControls <- error_child_generator(
  "HTTPBlockedByWindowsParentalControls",
  450
)

#' @export
#' @rdname Error-Classes
HTTPUnavailableForLegalReasons <- error_child_generator(
  "HTTPUnavailableForLegalReasons",
  451
)

#' @export
#' @rdname Error-Classes
HTTPRequestHeaderTooLarge <- error_child_generator(
  "HTTPRequestHeaderTooLarge",
  494
)

#' @export
#' @rdname Error-Classes
HTTPCertError <- error_child_generator("HTTPCertError", 495)

#' @export
#' @rdname Error-Classes
HTTPNoCert <- error_child_generator("HTTPNoCert", 496)

#' @export
#' @rdname Error-Classes
HTTPHTTPToHTTPS <- error_child_generator("HTTPHTTPToHTTPS", 497)

#' @export
#' @rdname Error-Classes
HTTPTokenExpiredInvalid <- error_child_generator("HTTPTokenExpiredInvalid", 498)

#' @export
#' @rdname Error-Classes
HTTPClientClosedRequest <- error_child_generator("HTTPClientClosedRequest", 499)


# 500 ----------------------

#' @export
#' @rdname Error-Classes
HTTPInternalServerError <- error_child_generator("HTTPInternalServerError", 500)

#' @export
#' @rdname Error-Classes
HTTPNotImplemented <- error_child_generator("HTTPNotImplemented", 501)

#' @export
#' @rdname Error-Classes
HTTPBadGateway <- error_child_generator("HTTPBadGateway", 502)

#' @export
#' @rdname Error-Classes
HTTPServiceUnavailable <- error_child_generator("HTTPServiceUnavailable", 503)

#' @export
#' @rdname Error-Classes
HTTPGatewayTimeout <- error_child_generator("HTTPGatewayTimeout", 504)

#' @export
#' @rdname Error-Classes
HTTPHTTPVersionNotSupported <- error_child_generator(
  "HTTPHTTPVersionNotSupported",
  505
)

#' @export
#' @rdname Error-Classes
HTTPVariantAlsoNegotiates <- error_child_generator(
  "HTTPVariantAlsoNegotiates",
  506
)

#' @export
#' @rdname Error-Classes
HTTPInsufficientStorage <- error_child_generator("HTTPInsufficientStorage", 507)

#' @export
#' @rdname Error-Classes
HTTPLoopDetected <- error_child_generator("HTTPLoopDetected", 508)

#' @export
#' @rdname Error-Classes
HTTPBandwidthLimitExceeded <- error_child_generator(
  "HTTPBandwidthLimitExceeded",
  509
)

#' @export
#' @rdname Error-Classes
HTTPNotExtended <- error_child_generator("HTTPNotExtended", 510)

#' @export
#' @rdname Error-Classes
HTTPNetworkAuthenticationRequired <- error_child_generator(
  "HTTPNetworkAuthenticationRequired",
  511
)

#' @export
#' @rdname Error-Classes
HTTPNetworkReadTimeoutError <- error_child_generator(
  "HTTPNetworkReadTimeoutError",
  598
)

#' @export
#' @rdname Error-Classes
HTTPNetworkConnectTimeoutError <- error_child_generator(
  "HTTPNetworkConnectTimeoutError",
  599
)


# Cloudflare
#' @export
#' @rdname Error-Classes
HTTPWebServerReturnedUnknownError <- error_child_generator(
  "HTTPWebServerReturnedUnknownError",
  520
)

#' @export
#' @rdname Error-Classes
HTTPWebServerIsDown <- error_child_generator("HTTPWebServerIsDown", 521)

#' @export
#' @rdname Error-Classes
HTTPConnectionTimedOut <- error_child_generator("HTTPConnectionTimedOut", 522)

#' @export
#' @rdname Error-Classes
HTTPOriginIsUnreachable <- error_child_generator("HTTPOriginIsUnreachable", 523)

#' @export
#' @rdname Error-Classes
HTTPATimeoutOccurred <- error_child_generator("HTTPATimeoutOccurred", 524)

#' @export
#' @rdname Error-Classes
HTTPSSLHandshakeFailed <- error_child_generator("HTTPSSLHandshakeFailed", 525)

#' @export
#' @rdname Error-Classes
HTTPInvalidSSLCertificate <- error_child_generator(
  "HTTPInvalidSSLCertificate ",
  526
)

#' @export
#' @rdname Error-Classes
HTTPRailgunError <- error_child_generator("HTTPRailgunError", 527)


## all children
fauxpas_env <- new.env()
assign(
  "http_children",
  list(
    HTTPContinue,
    HTTPSwitchProtocol,
    HTTPProcessing,
    HTTPOK,
    HTTPCreated,
    HTTPAccepted,
    HTTPNonAuthoritativeInformation,
    HTTPNoContent,
    HTTPResetContent,
    HTTPPartialContent,
    HTTPMultiStatus,
    HTTPAlreadyReported,
    HTTPImUsed,
    HTTPMultipleChoices,
    HTTPMovedPermanently,
    HTTPFound,
    HTTPSeeOther,
    HTTPNotModified,
    HTTPUseProxy,
    HTTPSwitchProxy,
    HTTPTemporaryRedirect,
    HTTPPermanentRedirect,
    HTTPBadRequest,
    HTTPUnauthorized,
    HTTPPaymentRequired,
    HTTPForbidden,
    HTTPNotFound,
    HTTPMethodNotAllowed,
    HTTPNotAcceptable,
    HTTPProxyAuthenticationRequired,
    HTTPRequestTimeout,
    HTTPConflict,
    HTTPGone,
    HTTPLengthRequired,
    HTTPPreconditionFailed,
    HTTPRequestEntityTooLarge,
    HTTPRequestURITooLong,
    HTTPUnsupportedMediaType,
    HTTPRequestRangeNotSatisfiable,
    HTTPExpectationFailed,
    HTTPTeaPot,
    HTTPAuthenticationTimeout,
    HTTPMethodFailure,
    HTTPMisdirectedRequest,
    HTTPUnprocessableEntity,
    HTTPLocked,
    HTTPFailedDependency,
    HTTPUnorderedCollection,
    HTTPUpgradeRequired,
    HTTPPreconditionRequired,
    HTTPTooManyRequests,
    HTTPRequestHeaderFieldsTooLarge,
    HTTPLoginTimeout,
    HTTPNoResponse,
    HTTPRetryWith,
    HTTPBlockedByWindowsParentalControls,
    HTTPUnavailableForLegalReasons,
    HTTPRequestHeaderTooLarge,
    HTTPCertError,
    HTTPNoCert,
    HTTPHTTPToHTTPS,
    HTTPTokenExpiredInvalid,
    HTTPClientClosedRequest,
    HTTPInternalServerError,
    HTTPNotImplemented,
    HTTPBadGateway,
    HTTPServiceUnavailable,
    HTTPGatewayTimeout,
    HTTPHTTPVersionNotSupported,
    HTTPVariantAlsoNegotiates,
    HTTPInsufficientStorage,
    HTTPLoopDetected,
    HTTPBandwidthLimitExceeded,
    HTTPNotExtended,
    HTTPNetworkAuthenticationRequired,
    HTTPNetworkReadTimeoutError,
    HTTPNetworkConnectTimeoutError,
    HTTPWebServerReturnedUnknownError,
    HTTPWebServerIsDown,
    HTTPConnectionTimedOut,
    HTTPOriginIsUnreachable,
    HTTPATimeoutOccurred,
    HTTPSSLHandshakeFailed,
    HTTPInvalidSSLCertificate,
    HTTPRailgunError
  ),
  envir = fauxpas_env
)
