// Package api provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
package api

import (
	"bytes"
	"compress/gzip"
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"path"
	"strings"
	"time"

	"github.com/getkin/kin-openapi/openapi3"
	"github.com/gorilla/mux"
	"github.com/oapi-codegen/runtime"
	strictnethttp "github.com/oapi-codegen/runtime/strictmiddleware/nethttp"
)

// Bucket defines model for Bucket.
type Bucket struct {
	// CreatedAt Creation timestamp of the bucket
	CreatedAt *time.Time `json:"created_at,omitempty"`

	// Name The name of the bucket
	Name *string `json:"name,omitempty"`
}

// Object defines model for Object.
type Object struct {
	// Key The key (identifier) of the object
	Key *string `json:"key,omitempty"`

	// LastModified The last modified timestamp of the object
	LastModified *time.Time `json:"last_modified,omitempty"`

	// Size The size of the object in bytes
	Size *int `json:"size,omitempty"`
}

// GetBucketsParams defines parameters for GetBuckets.
type GetBucketsParams struct {
	// Limit The maximum number of items to return
	Limit *int `form:"limit,omitempty" json:"limit,omitempty"`

	// Offset The number of items to skip before starting to collect the result set
	Offset *int `form:"offset,omitempty" json:"offset,omitempty"`
}

// PostBucketsJSONBody defines parameters for PostBuckets.
type PostBucketsJSONBody struct {
	// Name Name of the bucket to be created
	Name *string `json:"name,omitempty"`
}

// GetBucketsBucketNameObjectsParams defines parameters for GetBucketsBucketNameObjects.
type GetBucketsBucketNameObjectsParams struct {
	// Limit The maximum number of items to return
	Limit *int `form:"limit,omitempty" json:"limit,omitempty"`

	// Offset The number of items to skip before starting to collect the result set
	Offset *int `form:"offset,omitempty" json:"offset,omitempty"`
}

// PostBucketsJSONRequestBody defines body for PostBuckets for application/json ContentType.
type PostBucketsJSONRequestBody PostBucketsJSONBody

// ServerInterface represents all server handlers.
type ServerInterface interface {
	// List all buckets
	// (GET /buckets)
	GetBuckets(w http.ResponseWriter, r *http.Request, params GetBucketsParams)
	// Create a new bucket
	// (POST /buckets)
	PostBuckets(w http.ResponseWriter, r *http.Request)
	// Delete a bucket
	// (DELETE /buckets/{bucketName})
	DeleteBucketsBucketName(w http.ResponseWriter, r *http.Request, bucketName string)
	// List objects in a bucket
	// (GET /buckets/{bucketName}/objects)
	GetBucketsBucketNameObjects(w http.ResponseWriter, r *http.Request, bucketName string, params GetBucketsBucketNameObjectsParams)
	// Delete an object
	// (DELETE /buckets/{bucketName}/objects/{objectKey})
	DeleteBucketsBucketNameObjectsObjectKey(w http.ResponseWriter, r *http.Request, bucketName string, objectKey string)
	// Get object
	// (GET /buckets/{bucketName}/objects/{objectKey})
	GetBucketsBucketNameObjectsObjectKey(w http.ResponseWriter, r *http.Request, bucketName string, objectKey string)
	// Upload an object
	// (PUT /buckets/{bucketName}/objects/{objectKey})
	PutBucketsBucketNameObjectsObjectKey(w http.ResponseWriter, r *http.Request, bucketName string, objectKey string)
}

// ServerInterfaceWrapper converts contexts to parameters.
type ServerInterfaceWrapper struct {
	Handler            ServerInterface
	HandlerMiddlewares []MiddlewareFunc
	ErrorHandlerFunc   func(w http.ResponseWriter, r *http.Request, err error)
}

type MiddlewareFunc func(http.Handler) http.Handler

// GetBuckets operation middleware
func (siw *ServerInterfaceWrapper) GetBuckets(w http.ResponseWriter, r *http.Request) {

	var err error

	// Parameter object where we will unmarshal all parameters from the context
	var params GetBucketsParams

	// ------------- Optional query parameter "limit" -------------

	err = runtime.BindQueryParameter("form", true, false, "limit", r.URL.Query(), &params.Limit)
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "limit", Err: err})
		return
	}

	// ------------- Optional query parameter "offset" -------------

	err = runtime.BindQueryParameter("form", true, false, "offset", r.URL.Query(), &params.Offset)
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "offset", Err: err})
		return
	}

	handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		siw.Handler.GetBuckets(w, r, params)
	}))

	for _, middleware := range siw.HandlerMiddlewares {
		handler = middleware(handler)
	}

	handler.ServeHTTP(w, r)
}

// PostBuckets operation middleware
func (siw *ServerInterfaceWrapper) PostBuckets(w http.ResponseWriter, r *http.Request) {

	handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		siw.Handler.PostBuckets(w, r)
	}))

	for _, middleware := range siw.HandlerMiddlewares {
		handler = middleware(handler)
	}

	handler.ServeHTTP(w, r)
}

// DeleteBucketsBucketName operation middleware
func (siw *ServerInterfaceWrapper) DeleteBucketsBucketName(w http.ResponseWriter, r *http.Request) {

	var err error

	// ------------- Path parameter "bucketName" -------------
	var bucketName string

	err = runtime.BindStyledParameterWithOptions("simple", "bucketName", mux.Vars(r)["bucketName"], &bucketName, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "bucketName", Err: err})
		return
	}

	handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		siw.Handler.DeleteBucketsBucketName(w, r, bucketName)
	}))

	for _, middleware := range siw.HandlerMiddlewares {
		handler = middleware(handler)
	}

	handler.ServeHTTP(w, r)
}

// GetBucketsBucketNameObjects operation middleware
func (siw *ServerInterfaceWrapper) GetBucketsBucketNameObjects(w http.ResponseWriter, r *http.Request) {

	var err error

	// ------------- Path parameter "bucketName" -------------
	var bucketName string

	err = runtime.BindStyledParameterWithOptions("simple", "bucketName", mux.Vars(r)["bucketName"], &bucketName, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "bucketName", Err: err})
		return
	}

	// Parameter object where we will unmarshal all parameters from the context
	var params GetBucketsBucketNameObjectsParams

	// ------------- Optional query parameter "limit" -------------

	err = runtime.BindQueryParameter("form", true, false, "limit", r.URL.Query(), &params.Limit)
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "limit", Err: err})
		return
	}

	// ------------- Optional query parameter "offset" -------------

	err = runtime.BindQueryParameter("form", true, false, "offset", r.URL.Query(), &params.Offset)
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "offset", Err: err})
		return
	}

	handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		siw.Handler.GetBucketsBucketNameObjects(w, r, bucketName, params)
	}))

	for _, middleware := range siw.HandlerMiddlewares {
		handler = middleware(handler)
	}

	handler.ServeHTTP(w, r)
}

// DeleteBucketsBucketNameObjectsObjectKey operation middleware
func (siw *ServerInterfaceWrapper) DeleteBucketsBucketNameObjectsObjectKey(w http.ResponseWriter, r *http.Request) {

	var err error

	// ------------- Path parameter "bucketName" -------------
	var bucketName string

	err = runtime.BindStyledParameterWithOptions("simple", "bucketName", mux.Vars(r)["bucketName"], &bucketName, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "bucketName", Err: err})
		return
	}

	// ------------- Path parameter "objectKey" -------------
	var objectKey string

	err = runtime.BindStyledParameterWithOptions("simple", "objectKey", mux.Vars(r)["objectKey"], &objectKey, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "objectKey", Err: err})
		return
	}

	handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		siw.Handler.DeleteBucketsBucketNameObjectsObjectKey(w, r, bucketName, objectKey)
	}))

	for _, middleware := range siw.HandlerMiddlewares {
		handler = middleware(handler)
	}

	handler.ServeHTTP(w, r)
}

// GetBucketsBucketNameObjectsObjectKey operation middleware
func (siw *ServerInterfaceWrapper) GetBucketsBucketNameObjectsObjectKey(w http.ResponseWriter, r *http.Request) {

	var err error

	// ------------- Path parameter "bucketName" -------------
	var bucketName string

	err = runtime.BindStyledParameterWithOptions("simple", "bucketName", mux.Vars(r)["bucketName"], &bucketName, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "bucketName", Err: err})
		return
	}

	// ------------- Path parameter "objectKey" -------------
	var objectKey string

	err = runtime.BindStyledParameterWithOptions("simple", "objectKey", mux.Vars(r)["objectKey"], &objectKey, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "objectKey", Err: err})
		return
	}

	handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		siw.Handler.GetBucketsBucketNameObjectsObjectKey(w, r, bucketName, objectKey)
	}))

	for _, middleware := range siw.HandlerMiddlewares {
		handler = middleware(handler)
	}

	handler.ServeHTTP(w, r)
}

// PutBucketsBucketNameObjectsObjectKey operation middleware
func (siw *ServerInterfaceWrapper) PutBucketsBucketNameObjectsObjectKey(w http.ResponseWriter, r *http.Request) {

	var err error

	// ------------- Path parameter "bucketName" -------------
	var bucketName string

	err = runtime.BindStyledParameterWithOptions("simple", "bucketName", mux.Vars(r)["bucketName"], &bucketName, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "bucketName", Err: err})
		return
	}

	// ------------- Path parameter "objectKey" -------------
	var objectKey string

	err = runtime.BindStyledParameterWithOptions("simple", "objectKey", mux.Vars(r)["objectKey"], &objectKey, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "objectKey", Err: err})
		return
	}

	handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		siw.Handler.PutBucketsBucketNameObjectsObjectKey(w, r, bucketName, objectKey)
	}))

	for _, middleware := range siw.HandlerMiddlewares {
		handler = middleware(handler)
	}

	handler.ServeHTTP(w, r)
}

type UnescapedCookieParamError struct {
	ParamName string
	Err       error
}

func (e *UnescapedCookieParamError) Error() string {
	return fmt.Sprintf("error unescaping cookie parameter '%s'", e.ParamName)
}

func (e *UnescapedCookieParamError) Unwrap() error {
	return e.Err
}

type UnmarshalingParamError struct {
	ParamName string
	Err       error
}

func (e *UnmarshalingParamError) Error() string {
	return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error())
}

func (e *UnmarshalingParamError) Unwrap() error {
	return e.Err
}

type RequiredParamError struct {
	ParamName string
}

func (e *RequiredParamError) Error() string {
	return fmt.Sprintf("Query argument %s is required, but not found", e.ParamName)
}

type RequiredHeaderError struct {
	ParamName string
	Err       error
}

func (e *RequiredHeaderError) Error() string {
	return fmt.Sprintf("Header parameter %s is required, but not found", e.ParamName)
}

func (e *RequiredHeaderError) Unwrap() error {
	return e.Err
}

type InvalidParamFormatError struct {
	ParamName string
	Err       error
}

func (e *InvalidParamFormatError) Error() string {
	return fmt.Sprintf("Invalid format for parameter %s: %s", e.ParamName, e.Err.Error())
}

func (e *InvalidParamFormatError) Unwrap() error {
	return e.Err
}

type TooManyValuesForParamError struct {
	ParamName string
	Count     int
}

func (e *TooManyValuesForParamError) Error() string {
	return fmt.Sprintf("Expected one value for %s, got %d", e.ParamName, e.Count)
}

// Handler creates http.Handler with routing matching OpenAPI spec.
func Handler(si ServerInterface) http.Handler {
	return HandlerWithOptions(si, GorillaServerOptions{})
}

type GorillaServerOptions struct {
	BaseURL          string
	BaseRouter       *mux.Router
	Middlewares      []MiddlewareFunc
	ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
}

// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
func HandlerFromMux(si ServerInterface, r *mux.Router) http.Handler {
	return HandlerWithOptions(si, GorillaServerOptions{
		BaseRouter: r,
	})
}

func HandlerFromMuxWithBaseURL(si ServerInterface, r *mux.Router, baseURL string) http.Handler {
	return HandlerWithOptions(si, GorillaServerOptions{
		BaseURL:    baseURL,
		BaseRouter: r,
	})
}

// HandlerWithOptions creates http.Handler with additional options
func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.Handler {
	r := options.BaseRouter

	if r == nil {
		r = mux.NewRouter()
	}
	if options.ErrorHandlerFunc == nil {
		options.ErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) {
			http.Error(w, err.Error(), http.StatusBadRequest)
		}
	}
	wrapper := ServerInterfaceWrapper{
		Handler:            si,
		HandlerMiddlewares: options.Middlewares,
		ErrorHandlerFunc:   options.ErrorHandlerFunc,
	}

	r.HandleFunc(options.BaseURL+"/buckets", wrapper.GetBuckets).Methods("GET")

	r.HandleFunc(options.BaseURL+"/buckets", wrapper.PostBuckets).Methods("POST")

	r.HandleFunc(options.BaseURL+"/buckets/{bucketName}", wrapper.DeleteBucketsBucketName).Methods("DELETE")

	r.HandleFunc(options.BaseURL+"/buckets/{bucketName}/objects", wrapper.GetBucketsBucketNameObjects).Methods("GET")

	r.HandleFunc(options.BaseURL+"/buckets/{bucketName}/objects/{objectKey}", wrapper.DeleteBucketsBucketNameObjectsObjectKey).Methods("DELETE")

	r.HandleFunc(options.BaseURL+"/buckets/{bucketName}/objects/{objectKey}", wrapper.GetBucketsBucketNameObjectsObjectKey).Methods("GET")

	r.HandleFunc(options.BaseURL+"/buckets/{bucketName}/objects/{objectKey}", wrapper.PutBucketsBucketNameObjectsObjectKey).Methods("PUT")

	return r
}

type GetBucketsRequestObject struct {
	Params GetBucketsParams
}

type GetBucketsResponseObject interface {
	VisitGetBucketsResponse(w http.ResponseWriter) error
}

type GetBuckets200JSONResponse struct {
	Items *[]Bucket `json:"items,omitempty"`

	// Total Total number of buckets available
	Total *int `json:"total,omitempty"`
}

func (response GetBuckets200JSONResponse) VisitGetBucketsResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(200)

	return json.NewEncoder(w).Encode(response)
}

type PostBucketsRequestObject struct {
	Body *PostBucketsJSONRequestBody
}

type PostBucketsResponseObject interface {
	VisitPostBucketsResponse(w http.ResponseWriter) error
}

type PostBuckets201Response struct {
}

func (response PostBuckets201Response) VisitPostBucketsResponse(w http.ResponseWriter) error {
	w.WriteHeader(201)
	return nil
}

type PostBuckets400Response struct {
}

func (response PostBuckets400Response) VisitPostBucketsResponse(w http.ResponseWriter) error {
	w.WriteHeader(400)
	return nil
}

type PostBuckets409Response struct {
}

func (response PostBuckets409Response) VisitPostBucketsResponse(w http.ResponseWriter) error {
	w.WriteHeader(409)
	return nil
}

type DeleteBucketsBucketNameRequestObject struct {
	BucketName string `json:"bucketName"`
}

type DeleteBucketsBucketNameResponseObject interface {
	VisitDeleteBucketsBucketNameResponse(w http.ResponseWriter) error
}

type DeleteBucketsBucketName204Response struct {
}

func (response DeleteBucketsBucketName204Response) VisitDeleteBucketsBucketNameResponse(w http.ResponseWriter) error {
	w.WriteHeader(204)
	return nil
}

type DeleteBucketsBucketName404Response struct {
}

func (response DeleteBucketsBucketName404Response) VisitDeleteBucketsBucketNameResponse(w http.ResponseWriter) error {
	w.WriteHeader(404)
	return nil
}

type GetBucketsBucketNameObjectsRequestObject struct {
	BucketName string `json:"bucketName"`
	Params     GetBucketsBucketNameObjectsParams
}

type GetBucketsBucketNameObjectsResponseObject interface {
	VisitGetBucketsBucketNameObjectsResponse(w http.ResponseWriter) error
}

type GetBucketsBucketNameObjects200JSONResponse struct {
	Items *[]Object `json:"items,omitempty"`

	// Total Total number of objects available in the bucket
	Total *int `json:"total,omitempty"`
}

func (response GetBucketsBucketNameObjects200JSONResponse) VisitGetBucketsBucketNameObjectsResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(200)

	return json.NewEncoder(w).Encode(response)
}

type GetBucketsBucketNameObjects404Response struct {
}

func (response GetBucketsBucketNameObjects404Response) VisitGetBucketsBucketNameObjectsResponse(w http.ResponseWriter) error {
	w.WriteHeader(404)
	return nil
}

type DeleteBucketsBucketNameObjectsObjectKeyRequestObject struct {
	BucketName string `json:"bucketName"`
	ObjectKey  string `json:"objectKey"`
}

type DeleteBucketsBucketNameObjectsObjectKeyResponseObject interface {
	VisitDeleteBucketsBucketNameObjectsObjectKeyResponse(w http.ResponseWriter) error
}

type DeleteBucketsBucketNameObjectsObjectKey204Response struct {
}

func (response DeleteBucketsBucketNameObjectsObjectKey204Response) VisitDeleteBucketsBucketNameObjectsObjectKeyResponse(w http.ResponseWriter) error {
	w.WriteHeader(204)
	return nil
}

type DeleteBucketsBucketNameObjectsObjectKey404Response struct {
}

func (response DeleteBucketsBucketNameObjectsObjectKey404Response) VisitDeleteBucketsBucketNameObjectsObjectKeyResponse(w http.ResponseWriter) error {
	w.WriteHeader(404)
	return nil
}

type GetBucketsBucketNameObjectsObjectKeyRequestObject struct {
	BucketName string `json:"bucketName"`
	ObjectKey  string `json:"objectKey"`
}

type GetBucketsBucketNameObjectsObjectKeyResponseObject interface {
	VisitGetBucketsBucketNameObjectsObjectKeyResponse(w http.ResponseWriter) error
}

type GetBucketsBucketNameObjectsObjectKey200ApplicationoctetStreamResponse struct {
	Body          io.Reader
	ContentLength int64
}

func (response GetBucketsBucketNameObjectsObjectKey200ApplicationoctetStreamResponse) VisitGetBucketsBucketNameObjectsObjectKeyResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/octet-stream")
	if response.ContentLength != 0 {
		w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
	}
	w.WriteHeader(200)

	if closer, ok := response.Body.(io.ReadCloser); ok {
		defer closer.Close()
	}
	_, err := io.Copy(w, response.Body)
	return err
}

type GetBucketsBucketNameObjectsObjectKey404Response struct {
}

func (response GetBucketsBucketNameObjectsObjectKey404Response) VisitGetBucketsBucketNameObjectsObjectKeyResponse(w http.ResponseWriter) error {
	w.WriteHeader(404)
	return nil
}

type PutBucketsBucketNameObjectsObjectKeyRequestObject struct {
	BucketName string `json:"bucketName"`
	ObjectKey  string `json:"objectKey"`
	Body       io.Reader
}

type PutBucketsBucketNameObjectsObjectKeyResponseObject interface {
	VisitPutBucketsBucketNameObjectsObjectKeyResponse(w http.ResponseWriter) error
}

type PutBucketsBucketNameObjectsObjectKey201Response struct {
}

func (response PutBucketsBucketNameObjectsObjectKey201Response) VisitPutBucketsBucketNameObjectsObjectKeyResponse(w http.ResponseWriter) error {
	w.WriteHeader(201)
	return nil
}

type PutBucketsBucketNameObjectsObjectKey400Response struct {
}

func (response PutBucketsBucketNameObjectsObjectKey400Response) VisitPutBucketsBucketNameObjectsObjectKeyResponse(w http.ResponseWriter) error {
	w.WriteHeader(400)
	return nil
}

// StrictServerInterface represents all server handlers.
type StrictServerInterface interface {
	// List all buckets
	// (GET /buckets)
	GetBuckets(ctx context.Context, request GetBucketsRequestObject) (GetBucketsResponseObject, error)
	// Create a new bucket
	// (POST /buckets)
	PostBuckets(ctx context.Context, request PostBucketsRequestObject) (PostBucketsResponseObject, error)
	// Delete a bucket
	// (DELETE /buckets/{bucketName})
	DeleteBucketsBucketName(ctx context.Context, request DeleteBucketsBucketNameRequestObject) (DeleteBucketsBucketNameResponseObject, error)
	// List objects in a bucket
	// (GET /buckets/{bucketName}/objects)
	GetBucketsBucketNameObjects(ctx context.Context, request GetBucketsBucketNameObjectsRequestObject) (GetBucketsBucketNameObjectsResponseObject, error)
	// Delete an object
	// (DELETE /buckets/{bucketName}/objects/{objectKey})
	DeleteBucketsBucketNameObjectsObjectKey(ctx context.Context, request DeleteBucketsBucketNameObjectsObjectKeyRequestObject) (DeleteBucketsBucketNameObjectsObjectKeyResponseObject, error)
	// Get object
	// (GET /buckets/{bucketName}/objects/{objectKey})
	GetBucketsBucketNameObjectsObjectKey(ctx context.Context, request GetBucketsBucketNameObjectsObjectKeyRequestObject) (GetBucketsBucketNameObjectsObjectKeyResponseObject, error)
	// Upload an object
	// (PUT /buckets/{bucketName}/objects/{objectKey})
	PutBucketsBucketNameObjectsObjectKey(ctx context.Context, request PutBucketsBucketNameObjectsObjectKeyRequestObject) (PutBucketsBucketNameObjectsObjectKeyResponseObject, error)
}

type StrictHandlerFunc = strictnethttp.StrictHTTPHandlerFunc
type StrictMiddlewareFunc = strictnethttp.StrictHTTPMiddlewareFunc

type StrictHTTPServerOptions struct {
	RequestErrorHandlerFunc  func(w http.ResponseWriter, r *http.Request, err error)
	ResponseErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
}

func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
	return &strictHandler{ssi: ssi, middlewares: middlewares, options: StrictHTTPServerOptions{
		RequestErrorHandlerFunc: func(w http.ResponseWriter, r *http.Request, err error) {
			http.Error(w, err.Error(), http.StatusBadRequest)
		},
		ResponseErrorHandlerFunc: func(w http.ResponseWriter, r *http.Request, err error) {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		},
	}}
}

func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface {
	return &strictHandler{ssi: ssi, middlewares: middlewares, options: options}
}

type strictHandler struct {
	ssi         StrictServerInterface
	middlewares []StrictMiddlewareFunc
	options     StrictHTTPServerOptions
}

// GetBuckets operation middleware
func (sh *strictHandler) GetBuckets(w http.ResponseWriter, r *http.Request, params GetBucketsParams) {
	var request GetBucketsRequestObject

	request.Params = params

	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
		return sh.ssi.GetBuckets(ctx, request.(GetBucketsRequestObject))
	}
	for _, middleware := range sh.middlewares {
		handler = middleware(handler, "GetBuckets")
	}

	response, err := handler(r.Context(), w, r, request)

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(GetBucketsResponseObject); ok {
		if err := validResponse.VisitGetBucketsResponse(w); err != nil {
			sh.options.ResponseErrorHandlerFunc(w, r, err)
		}
	} else if response != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response))
	}
}

// PostBuckets operation middleware
func (sh *strictHandler) PostBuckets(w http.ResponseWriter, r *http.Request) {
	var request PostBucketsRequestObject

	var body PostBucketsJSONRequestBody
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err))
		return
	}
	request.Body = &body

	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
		return sh.ssi.PostBuckets(ctx, request.(PostBucketsRequestObject))
	}
	for _, middleware := range sh.middlewares {
		handler = middleware(handler, "PostBuckets")
	}

	response, err := handler(r.Context(), w, r, request)

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(PostBucketsResponseObject); ok {
		if err := validResponse.VisitPostBucketsResponse(w); err != nil {
			sh.options.ResponseErrorHandlerFunc(w, r, err)
		}
	} else if response != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response))
	}
}

// DeleteBucketsBucketName operation middleware
func (sh *strictHandler) DeleteBucketsBucketName(w http.ResponseWriter, r *http.Request, bucketName string) {
	var request DeleteBucketsBucketNameRequestObject

	request.BucketName = bucketName

	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
		return sh.ssi.DeleteBucketsBucketName(ctx, request.(DeleteBucketsBucketNameRequestObject))
	}
	for _, middleware := range sh.middlewares {
		handler = middleware(handler, "DeleteBucketsBucketName")
	}

	response, err := handler(r.Context(), w, r, request)

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(DeleteBucketsBucketNameResponseObject); ok {
		if err := validResponse.VisitDeleteBucketsBucketNameResponse(w); err != nil {
			sh.options.ResponseErrorHandlerFunc(w, r, err)
		}
	} else if response != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response))
	}
}

// GetBucketsBucketNameObjects operation middleware
func (sh *strictHandler) GetBucketsBucketNameObjects(w http.ResponseWriter, r *http.Request, bucketName string, params GetBucketsBucketNameObjectsParams) {
	var request GetBucketsBucketNameObjectsRequestObject

	request.BucketName = bucketName
	request.Params = params

	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
		return sh.ssi.GetBucketsBucketNameObjects(ctx, request.(GetBucketsBucketNameObjectsRequestObject))
	}
	for _, middleware := range sh.middlewares {
		handler = middleware(handler, "GetBucketsBucketNameObjects")
	}

	response, err := handler(r.Context(), w, r, request)

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(GetBucketsBucketNameObjectsResponseObject); ok {
		if err := validResponse.VisitGetBucketsBucketNameObjectsResponse(w); err != nil {
			sh.options.ResponseErrorHandlerFunc(w, r, err)
		}
	} else if response != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response))
	}
}

// DeleteBucketsBucketNameObjectsObjectKey operation middleware
func (sh *strictHandler) DeleteBucketsBucketNameObjectsObjectKey(w http.ResponseWriter, r *http.Request, bucketName string, objectKey string) {
	var request DeleteBucketsBucketNameObjectsObjectKeyRequestObject

	request.BucketName = bucketName
	request.ObjectKey = objectKey

	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
		return sh.ssi.DeleteBucketsBucketNameObjectsObjectKey(ctx, request.(DeleteBucketsBucketNameObjectsObjectKeyRequestObject))
	}
	for _, middleware := range sh.middlewares {
		handler = middleware(handler, "DeleteBucketsBucketNameObjectsObjectKey")
	}

	response, err := handler(r.Context(), w, r, request)

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(DeleteBucketsBucketNameObjectsObjectKeyResponseObject); ok {
		if err := validResponse.VisitDeleteBucketsBucketNameObjectsObjectKeyResponse(w); err != nil {
			sh.options.ResponseErrorHandlerFunc(w, r, err)
		}
	} else if response != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response))
	}
}

// GetBucketsBucketNameObjectsObjectKey operation middleware
func (sh *strictHandler) GetBucketsBucketNameObjectsObjectKey(w http.ResponseWriter, r *http.Request, bucketName string, objectKey string) {
	var request GetBucketsBucketNameObjectsObjectKeyRequestObject

	request.BucketName = bucketName
	request.ObjectKey = objectKey

	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
		return sh.ssi.GetBucketsBucketNameObjectsObjectKey(ctx, request.(GetBucketsBucketNameObjectsObjectKeyRequestObject))
	}
	for _, middleware := range sh.middlewares {
		handler = middleware(handler, "GetBucketsBucketNameObjectsObjectKey")
	}

	response, err := handler(r.Context(), w, r, request)

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(GetBucketsBucketNameObjectsObjectKeyResponseObject); ok {
		if err := validResponse.VisitGetBucketsBucketNameObjectsObjectKeyResponse(w); err != nil {
			sh.options.ResponseErrorHandlerFunc(w, r, err)
		}
	} else if response != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response))
	}
}

// PutBucketsBucketNameObjectsObjectKey operation middleware
func (sh *strictHandler) PutBucketsBucketNameObjectsObjectKey(w http.ResponseWriter, r *http.Request, bucketName string, objectKey string) {
	var request PutBucketsBucketNameObjectsObjectKeyRequestObject

	request.BucketName = bucketName
	request.ObjectKey = objectKey

	request.Body = r.Body

	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
		return sh.ssi.PutBucketsBucketNameObjectsObjectKey(ctx, request.(PutBucketsBucketNameObjectsObjectKeyRequestObject))
	}
	for _, middleware := range sh.middlewares {
		handler = middleware(handler, "PutBucketsBucketNameObjectsObjectKey")
	}

	response, err := handler(r.Context(), w, r, request)

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(PutBucketsBucketNameObjectsObjectKeyResponseObject); ok {
		if err := validResponse.VisitPutBucketsBucketNameObjectsObjectKeyResponse(w); err != nil {
			sh.options.ResponseErrorHandlerFunc(w, r, err)
		}
	} else if response != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response))
	}
}

// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{

	"H4sIAAAAAAAC/+xY328jNRD+VyzDA0hpksK9sE9cQTpVIFpxxxM6nZzd2cRX/zp7Nu1S5X9HY3uTTXbT",
	"RumBELo3x/bOjOf75hs7j7y02lkDBgMvHnkoV6BFHF415R0gjZy3DjxKiPOlB4FQfRBxrYJQeulQWsML",
	"/hOtSWsYSg0BhXbM1gxXwBbJ2oTX1mv6lFcC4YL28QnH1gEveEAvzZJvJtwIDUPz71bAaGVg9OD7zXbG",
	"Lj5CiWTxJo0Gx7mDdtzRHbTsG1mBQVlL8N92TrPJkaCVCPhB24r2V+NGaQvrtgyztLV9WpaC/OtIlmhl",
	"3yiThi1ahLAzJA3CEvxYvmhKmtpGwK1BkVIHWkhFITTOWY8/woPQTsG0tJp3oPHXt9fsbdpAQe4HR4u1",
	"9UwLI5bSLHN0gcITpos1oPViCSyAX8sSphSzREXWE47sbd7x+vaaT/gafEj2L6fz6ZzcWgdGOMkL/n2c",
	"mnAncBUhnyXexPESRmj8O6CXsAYmmKMoie9MyYCUUqFUJl4MupfhHDVFSwyLlXBd8YK/AbzKLikMLzQg",
	"+MCLP8ew0+JB6kYz0+gFeHIpEXRgaJkHbLzhhA0v+KcGfLvLu5JaEndSDadT1aJRyIvL+XwM9dH6GnoN",
	"d9KxBdTWAwsoPBJuaFlplaJzUwo8hEYhC7Ecx6KzdZ0WR8IbC+79hHsIzpqQ6vS7+bwjI5iImXBOyTJm",
	"efYx0AEee8b3qzyeZW/wtYeaF/yr2U4AZ1n9Zln6dmUhvBdt/G1RqJGSo+le6jp+iLWQSiwUnFx0B9Uy",
	"wr9sexothEZr4Vte8F9pucdNitbZcEykidsG7vPuiDISvrkchxy+taFHYg+fGgh4Zav2BaiMq/xvA4Wn",
	"8BbAcufhE551hxdctxcG7i9O7wQ0RdFLTxqNvoHNgGmXw6DS0bsQWGjKEkKoG6UiL14ldh58IyqWE5X2",
	"/HDUrlAeRNUyeJCBsNuDdgSwuKPTsdljGlDiNsmFAhzJ7M9xnokurcJUkTISw3Hg00cZ+quto1OUzIwi",
	"maPLMkGqvFOJRd/+Pkx95ThEeSgWr46mOrkfg/D4N8Yiq21jqgNkDhJ6HJVZTu95LafrkfcSV9QnWXBQ",
	"pitE8vFUy9lBdpNjOAu5z4rX5F/re1/a3ult72Z7WT6z7XU83ba97oJ0KM8vboK9W+PO/vTcMo69s38R",
	"PbmeZ49p8Au0Jynv9oZbe6tj6M+X8hEBztV80/n/r5b1s++oEf+2d6jP3AXy++GcLmB9h95z/aCDmSw+",
	"I/fnMOIJcf9Chyfo8JSU2hIBLwJ6EHpfUrdv8YU0Imr7oaeBZL2LrSHe/KDqAK4EipdT7A1gj1yuGSHX",
	"H05ZUeX7YjZHhtfg771M/IwXzfj+NluVfp54t83/iHi19f8k8055IL2QdGe8Y7L8NZEipz5krs1aKHlA",
	"5D1WdpTbCV9cB7/uSNB4xQu+QnShmM2Ek9Pen0ez9SXfvN/8HQAA//+vpreTjhQAAA==",
}

// GetSwagger returns the content of the embedded swagger specification file
// or error if failed to decode
func decodeSpec() ([]byte, error) {
	zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
	if err != nil {
		return nil, fmt.Errorf("error base64 decoding spec: %w", err)
	}
	zr, err := gzip.NewReader(bytes.NewReader(zipped))
	if err != nil {
		return nil, fmt.Errorf("error decompressing spec: %w", err)
	}
	var buf bytes.Buffer
	_, err = buf.ReadFrom(zr)
	if err != nil {
		return nil, fmt.Errorf("error decompressing spec: %w", err)
	}

	return buf.Bytes(), nil
}

var rawSpec = decodeSpecCached()

// a naive cached of a decoded swagger spec
func decodeSpecCached() func() ([]byte, error) {
	data, err := decodeSpec()
	return func() ([]byte, error) {
		return data, err
	}
}

// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
	res := make(map[string]func() ([]byte, error))
	if len(pathToFile) > 0 {
		res[pathToFile] = rawSpec
	}

	return res
}

// GetSwagger returns the Swagger specification corresponding to the generated code
// in this file. The external references of Swagger specification are resolved.
// The logic of resolving external references is tightly connected to "import-mapping" feature.
// Externally referenced files must be embedded in the corresponding golang packages.
// Urls can be supported but this task was out of the scope.
func GetSwagger() (swagger *openapi3.T, err error) {
	resolvePath := PathToRawSpec("")

	loader := openapi3.NewLoader()
	loader.IsExternalRefsAllowed = true
	loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
		pathToFile := url.String()
		pathToFile = path.Clean(pathToFile)
		getSpec, ok := resolvePath[pathToFile]
		if !ok {
			err1 := fmt.Errorf("path not found: %s", pathToFile)
			return nil, err1
		}
		return getSpec()
	}
	var specData []byte
	specData, err = rawSpec()
	if err != nil {
		return
	}
	swagger, err = loader.LoadFromData(specData)
	if err != nil {
		return
	}
	return
}
