// Code generated by go-swagger; DO NOT EDIT.


{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}


package {{ .APIPackage }}

import (
	"context"
	"crypto/tls"
	"net/http"
	"log"
	"fmt"

	"github.com/go-openapi/errors"
	"github.com/go-openapi/loads"
	"github.com/go-openapi/runtime"
	"github.com/go-openapi/runtime/middleware"
	"github.com/go-openapi/runtime/security"

  {{ imports .DefaultImports }}
  {{ imports .Imports }}
)
{{ $package := .Package }}

type contextKey string

const AuthKey contextKey = "Auth"

{{ range .OperationGroups -}}
// go:generate mockery -name {{ pascalize .Name}}API -inpkg

/* {{ pascalize .Name }}API {{ .Description }} */
type {{ pascalize .Name }}API interface {
	/* Prepare action before the operation */
	Prepare(ctx context.Context, operation string, params interface{}) middleware.Responder

{{ range .Operations -}}
	{{ if .Summary -}}
	/* {{ pascalize .Name }} {{ .Summary }} */
	{{ else if .Description -}}
	/* {{ pascalize .Name }} {{ .Description }} */
	{{ end -}}
	{{ pascalize .Name }}(ctx context.Context, params {{.Package}}.{{ pascalize .Name }}Params) middleware.Responder

{{ end -}}
}
{{ end }}

// Config is configuration for Handler
type Config struct {
	{{ range .OperationGroups -}}
	{{ pascalize .Name }}API
	{{ end -}}
	Logger func(string, ...interface{})
	// InnerMiddleware is for the handler executors. These do not apply to the swagger.json document.
	// The middleware executes after routing but before authentication, binding and validation
	InnerMiddleware func(http.Handler) http.Handler

	// Authorizer is used to authorize a request after the Auth function was called using the "Auth*" functions
	// and the principal was stored in the context in the "AuthKey" context value.
	Authorizer func(*http.Request) error

	{{ range .SecurityDefinitions -}}
	{{ if .IsBasicAuth -}}
	// Auth{{ pascalize .ID }} for basic authentication
	Auth{{ pascalize .ID }} func(user string, pass string) (interface{}, error)
	{{ end -}}
	{{ if .IsAPIKeyAuth -}}
	// Auth{{ pascalize .ID }} Applies when the "{{ .Name }}" {{ .Source }} is set
	Auth{{ pascalize .ID }} func(token string) (interface{}, error)
	{{ end }}
	{{ if .IsOAuth2 -}}
	// Auth{{ pascalize .ID }} For OAuth2 authentication
	Auth{{ pascalize .ID }} func(token string, scopes []string) (interface{}, error)
	{{ end -}}
	{{ end -}}

	// Authenticator to use for all APIKey authentication
	APIKeyAuthenticator func(string, string, security.TokenAuthentication) runtime.Authenticator
	// Authenticator to use for all Bearer authentication
	BasicAuthenticator func(security.UserPassAuthentication) runtime.Authenticator
	// Authenticator to use for all Basic authentication
	BearerAuthenticator func(string, security.ScopedTokenAuthentication) runtime.Authenticator
}

// Handler returns an http.Handler given the handler configuration
// It mounts all the business logic implementers in the right routing.
func Handler(c Config) (http.Handler, error) {
	h, _, err := HandlerAPI(c)
	return h, err
}

// HandlerAPI returns an http.Handler given the handler configuration
// and the corresponding *{{ pascalize .Name }} instance.
// It mounts all the business logic implementers in the right routing.
func HandlerAPI(c Config) (http.Handler, *{{.Package}}.{{ pascalize .Name }}API, error) {
	spec, err := loads.Analyzed(swaggerCopy(SwaggerJSON), "")
	if err != nil {
		return nil, nil, fmt.Errorf("analyze swagger: %v", err)
	}
	api := {{.Package}}.New{{ pascalize .Name }}API(spec)
	api.ServeError = errors.ServeError
	api.Logger = c.Logger

	if c.APIKeyAuthenticator != nil {
		api.APIKeyAuthenticator = c.APIKeyAuthenticator
	}
	if c.BasicAuthenticator  != nil {
		api.BasicAuthenticator  = c.BasicAuthenticator
	}
	if c.BearerAuthenticator  != nil {
		api.BearerAuthenticator  = c.BearerAuthenticator
	}

	{{ range .Consumes -}}
	{{ if .Implementation -}}
	api.{{ pascalize .Name }}Consumer = {{ .Implementation }}
	{{ else }}
	api.{{ pascalize .Name }}Consumer = runtime.ConsumerFunc(func(r io.Reader, target interface{}) error {
		return errors.NotImplemented("{{.Name}} consumer has not yet been implemented")
	})
	{{ end -}}
	{{ end -}}
	{{ range .Produces -}}
	{{ if .Implementation -}}
	api.{{ pascalize .Name }}Producer = {{ .Implementation }}
	{{ else -}}
	api.{{ pascalize .Name }}Producer = runtime.ProducerFunc(func(w io.Writer, data interface{}) error {
		return errors.NotImplemented("{{.Name}} producer has not yet been implemented")
	})
	{{ end -}}
	{{ end -}}

	{{ range .SecurityDefinitions -}}
	{{ if .IsBasicAuth -}}
	api.{{ pascalize .ID }}Auth = func(user string, pass string) ({{if not ( eq .Principal "interface{}" )}}*{{ end }}{{.Principal}}, error) {
        if c.Auth{{ pascalize .ID }} == nil {
            return "", nil
        }
		return c.Auth{{ pascalize .ID }}(user, pass)
	}
	{{ end -}}
	{{ if .IsAPIKeyAuth -}}
	api.{{ pascalize .ID }}Auth = func(token string) ({{if not ( eq .Principal "interface{}" )}}*{{ end }}{{.Principal}}, error) {
	    if c.Auth{{ pascalize .ID }} == nil {
	        return token, nil
	    }
		return c.Auth{{ pascalize .ID }}(token)
	}
	{{ end }}
	{{ if .IsOAuth2 -}}
	api.{{ pascalize .ID }}Auth = func(token string, scopes []string) ({{if not ( eq .Principal "interface{}" )}}*{{ end }}{{.Principal}}, error) {
        if c.Auth{{ pascalize .ID }} == nil {
            return token, nil
        }
		return c.Auth{{ pascalize .ID }}(token, scopes)
	}
	{{ end -}}
	{{ end -}}

	{{ if .SecurityDefinitions -}}
	api.APIAuthorizer = authorizer(c.Authorizer)
	{{ end -}}

	{{ range .Operations -}}
	api.{{if ne .Package $package}}{{pascalize .Package}}{{end}}{{ pascalize .Name }}Handler =
    {{- .PackageAlias }}.{{ pascalize .Name }}HandlerFunc(func(params {{.PackageAlias}}.{{ pascalize .Name }}Params{{if .Authorized}}, principal interface{}{{end}}) middleware.Responder {
		ctx := params.HTTPRequest.Context()
		{{ if .Authorized -}}
		ctx = storeAuth(ctx, principal)
		{{ end -}}
		if api.BeforePrepare != nil {
			if res := api.BeforePrepare(ctx, "{{pascalize .Name}}", &params); res != nil {
				return res
			}
		}
		if res := c.{{pascalize .Package}}API.Prepare(ctx, "{{pascalize .Name}}", &params); res != nil {
			return res
		}
		return c.{{pascalize .Package}}API.{{pascalize .Name}}(ctx, params)
	})
	{{ end -}}

	api.ServerShutdown = func() {  }
	return api.Serve(c.InnerMiddleware), api, nil
}

// swaggerCopy copies the swagger json to prevent data races in runtime
func swaggerCopy(orig json.RawMessage) json.RawMessage {
	c := make(json.RawMessage, len(orig))
	copy(c, orig)
	return c
}

// authorizer is a helper function to implement the runtime.Authorizer interface.
type authorizer func(*http.Request) error

func (a authorizer) Authorize(req *http.Request, principal interface{}) error {
	if a == nil {
		return nil
	}
	ctx := storeAuth(req.Context(), principal)
	return a(req.WithContext(ctx))
}

func storeAuth(ctx context.Context, principal interface{}) context.Context {
	return context.WithValue(ctx, AuthKey, principal)
}
