// 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 (
	"context"
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/go-chi/chi/v5"
	"github.com/oapi-codegen/runtime"
	strictnethttp "github.com/oapi-codegen/runtime/strictmiddleware/nethttp"
)

// ServerInterface represents all server handlers.
type ServerInterface interface {
	// Disable blocking
	// (GET /blocking/disable)
	DisableBlocking(w http.ResponseWriter, r *http.Request, params DisableBlockingParams)
	// Enable blocking
	// (GET /blocking/enable)
	EnableBlocking(w http.ResponseWriter, r *http.Request)
	// Blocking status
	// (GET /blocking/status)
	BlockingStatus(w http.ResponseWriter, r *http.Request)
	// Clears the DNS response cache
	// (POST /cache/flush)
	CacheFlush(w http.ResponseWriter, r *http.Request)
	// List refresh
	// (POST /lists/refresh)
	ListRefresh(w http.ResponseWriter, r *http.Request)
	// Performs DNS query
	// (POST /query)
	Query(w http.ResponseWriter, r *http.Request)
}

// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint.

type Unimplemented struct{}

// Disable blocking
// (GET /blocking/disable)
func (_ Unimplemented) DisableBlocking(w http.ResponseWriter, r *http.Request, params DisableBlockingParams) {
	w.WriteHeader(http.StatusNotImplemented)
}

// Enable blocking
// (GET /blocking/enable)
func (_ Unimplemented) EnableBlocking(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNotImplemented)
}

// Blocking status
// (GET /blocking/status)
func (_ Unimplemented) BlockingStatus(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNotImplemented)
}

// Clears the DNS response cache
// (POST /cache/flush)
func (_ Unimplemented) CacheFlush(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNotImplemented)
}

// List refresh
// (POST /lists/refresh)
func (_ Unimplemented) ListRefresh(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNotImplemented)
}

// Performs DNS query
// (POST /query)
func (_ Unimplemented) Query(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNotImplemented)
}

// 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

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

	var err error

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

	// ------------- Optional query parameter "duration" -------------

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

	// ------------- Optional query parameter "groups" -------------

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

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

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

	handler.ServeHTTP(w, r)
}

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

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

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

	handler.ServeHTTP(w, r)
}

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

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

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

	handler.ServeHTTP(w, r)
}

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

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

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

	handler.ServeHTTP(w, r)
}

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

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

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

	handler.ServeHTTP(w, r)
}

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

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

	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, ChiServerOptions{})
}

type ChiServerOptions struct {
	BaseURL          string
	BaseRouter       chi.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 chi.Router) http.Handler {
	return HandlerWithOptions(si, ChiServerOptions{
		BaseRouter: r,
	})
}

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

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

	if r == nil {
		r = chi.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.Group(func(r chi.Router) {
		r.Get(options.BaseURL+"/blocking/disable", wrapper.DisableBlocking)
	})
	r.Group(func(r chi.Router) {
		r.Get(options.BaseURL+"/blocking/enable", wrapper.EnableBlocking)
	})
	r.Group(func(r chi.Router) {
		r.Get(options.BaseURL+"/blocking/status", wrapper.BlockingStatus)
	})
	r.Group(func(r chi.Router) {
		r.Post(options.BaseURL+"/cache/flush", wrapper.CacheFlush)
	})
	r.Group(func(r chi.Router) {
		r.Post(options.BaseURL+"/lists/refresh", wrapper.ListRefresh)
	})
	r.Group(func(r chi.Router) {
		r.Post(options.BaseURL+"/query", wrapper.Query)
	})

	return r
}

type DisableBlockingRequestObject struct {
	Params DisableBlockingParams
}

type DisableBlockingResponseObject interface {
	VisitDisableBlockingResponse(w http.ResponseWriter) error
}

type DisableBlocking200Response struct {
}

func (response DisableBlocking200Response) VisitDisableBlockingResponse(w http.ResponseWriter) error {
	w.WriteHeader(200)
	return nil
}

type DisableBlocking400TextResponse string

func (response DisableBlocking400TextResponse) VisitDisableBlockingResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "text/plain")
	w.WriteHeader(400)

	_, err := w.Write([]byte(response))
	return err
}

type EnableBlockingRequestObject struct {
}

type EnableBlockingResponseObject interface {
	VisitEnableBlockingResponse(w http.ResponseWriter) error
}

type EnableBlocking200Response struct {
}

func (response EnableBlocking200Response) VisitEnableBlockingResponse(w http.ResponseWriter) error {
	w.WriteHeader(200)
	return nil
}

type BlockingStatusRequestObject struct {
}

type BlockingStatusResponseObject interface {
	VisitBlockingStatusResponse(w http.ResponseWriter) error
}

type BlockingStatus200JSONResponse ApiBlockingStatus

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

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

type CacheFlushRequestObject struct {
}

type CacheFlushResponseObject interface {
	VisitCacheFlushResponse(w http.ResponseWriter) error
}

type CacheFlush200Response struct {
}

func (response CacheFlush200Response) VisitCacheFlushResponse(w http.ResponseWriter) error {
	w.WriteHeader(200)
	return nil
}

type ListRefreshRequestObject struct {
}

type ListRefreshResponseObject interface {
	VisitListRefreshResponse(w http.ResponseWriter) error
}

type ListRefresh200Response struct {
}

func (response ListRefresh200Response) VisitListRefreshResponse(w http.ResponseWriter) error {
	w.WriteHeader(200)
	return nil
}

type ListRefresh500TextResponse string

func (response ListRefresh500TextResponse) VisitListRefreshResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "text/plain")
	w.WriteHeader(500)

	_, err := w.Write([]byte(response))
	return err
}

type QueryRequestObject struct {
	Body *QueryJSONRequestBody
}

type QueryResponseObject interface {
	VisitQueryResponse(w http.ResponseWriter) error
}

type Query200JSONResponse ApiQueryResult

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

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

type Query400TextResponse string

func (response Query400TextResponse) VisitQueryResponse(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "text/plain")
	w.WriteHeader(400)

	_, err := w.Write([]byte(response))
	return err
}

// StrictServerInterface represents all server handlers.
type StrictServerInterface interface {
	// Disable blocking
	// (GET /blocking/disable)
	DisableBlocking(ctx context.Context, request DisableBlockingRequestObject) (DisableBlockingResponseObject, error)
	// Enable blocking
	// (GET /blocking/enable)
	EnableBlocking(ctx context.Context, request EnableBlockingRequestObject) (EnableBlockingResponseObject, error)
	// Blocking status
	// (GET /blocking/status)
	BlockingStatus(ctx context.Context, request BlockingStatusRequestObject) (BlockingStatusResponseObject, error)
	// Clears the DNS response cache
	// (POST /cache/flush)
	CacheFlush(ctx context.Context, request CacheFlushRequestObject) (CacheFlushResponseObject, error)
	// List refresh
	// (POST /lists/refresh)
	ListRefresh(ctx context.Context, request ListRefreshRequestObject) (ListRefreshResponseObject, error)
	// Performs DNS query
	// (POST /query)
	Query(ctx context.Context, request QueryRequestObject) (QueryResponseObject, 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
}

// DisableBlocking operation middleware
func (sh *strictHandler) DisableBlocking(w http.ResponseWriter, r *http.Request, params DisableBlockingParams) {
	var request DisableBlockingRequestObject

	request.Params = params

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

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

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(DisableBlockingResponseObject); ok {
		if err := validResponse.VisitDisableBlockingResponse(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))
	}
}

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

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

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

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(EnableBlockingResponseObject); ok {
		if err := validResponse.VisitEnableBlockingResponse(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))
	}
}

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

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

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

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(BlockingStatusResponseObject); ok {
		if err := validResponse.VisitBlockingStatusResponse(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))
	}
}

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

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

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

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(CacheFlushResponseObject); ok {
		if err := validResponse.VisitCacheFlushResponse(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))
	}
}

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

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

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

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(ListRefreshResponseObject); ok {
		if err := validResponse.VisitListRefreshResponse(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))
	}
}

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

	var body QueryJSONRequestBody
	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.Query(ctx, request.(QueryRequestObject))
	}
	for _, middleware := range sh.middlewares {
		handler = middleware(handler, "Query")
	}

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

	if err != nil {
		sh.options.ResponseErrorHandlerFunc(w, r, err)
	} else if validResponse, ok := response.(QueryResponseObject); ok {
		if err := validResponse.VisitQueryResponse(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))
	}
}
