package {{packageName}}

{{#featureMetrics}}
import com.codahale.metrics.Slf4jReporter
{{/featureMetrics}}
import io.ktor.application.*
import io.ktor.features.*
import io.ktor.gson.*
import io.ktor.http.*
{{#featureLocations}}
import io.ktor.locations.*
{{/featureLocations}}
{{#featureMetrics}}
import io.ktor.metrics.dropwizard.*
import java.util.concurrent.TimeUnit
{{/featureMetrics}}
import io.ktor.routing.*
import io.ktor.util.*
{{#hasAuthMethods}}
import com.typesafe.config.ConfigFactory
import io.ktor.auth.*
import io.ktor.client.HttpClient
import io.ktor.client.engine.apache.Apache
import io.ktor.config.HoconApplicationConfig
import org.openapitools.server.infrastructure.*
{{/hasAuthMethods}}
{{#generateApis}}{{#apiInfo}}{{#apis}}import {{apiPackage}}.{{classname}}
{{/apis}}{{/apiInfo}}{{/generateApis}}

{{#hasAuthMethods}}
internal val settings = HoconApplicationConfig(ConfigFactory.defaultApplication(HTTP::class.java.classLoader))

object HTTP {
    val client = HttpClient(Apache)
}
{{/hasAuthMethods}}

@KtorExperimentalAPI
{{#featureLocations}}
@KtorExperimentalLocationsAPI
{{/featureLocations}}
fun Application.main() {
    install(DefaultHeaders)
    {{#featureMetrics}}
    install(DropwizardMetrics) {
        val reporter = Slf4jReporter.forRegistry(registry)
            .outputTo(log)
            .convertRatesTo(TimeUnit.SECONDS)
            .convertDurationsTo(TimeUnit.MILLISECONDS)
            .build()
        reporter.start(10, TimeUnit.SECONDS)
    }
    {{/featureMetrics}}
{{#generateApis}}
    install(ContentNegotiation) {
        register(ContentType.Application.Json, GsonConverter())
    }
    {{#featureAutoHead}}
    install(AutoHeadResponse) // see https://ktor.io/docs/autoheadresponse.html
    {{/featureAutoHead}}
    {{#featureConditionalHeaders}}
    install(ConditionalHeaders) // see https://ktor.io/docs/conditional-headers.html
    {{/featureConditionalHeaders}}
    {{#featureCompression}}
    install(Compression, ApplicationCompressionConfiguration()) // see https://ktor.io/docs/compression.html
    {{/featureCompression}}
    {{#featureCORS}}
    install(CORS, ApplicationCORSConfiguration()) // see https://ktor.io/docs/cors.html
    {{/featureCORS}}
    {{#featureHSTS}}
    install(HSTS, ApplicationHstsConfiguration()) // see https://ktor.io/docs/hsts.html
    {{/featureHSTS}}
    {{#featureLocations}}
    install(Locations) // see https://ktor.io/docs/features-locations.html
    {{/featureLocations}}
    {{#hasAuthMethods}}
    install(Authentication) {
    {{#authMethods}}
        {{#isBasic}}
        basic("{{{name}}}") {
        validate { credentials ->
            // TODO: "Apply your basic authentication functionality."
            // Accessible in-method via call.principal<UserIdPrincipal>()
            if (credentials.name == "Swagger" && "Codegen" == credentials.password) {
                UserIdPrincipal(credentials.name)
            } else {
                null
            }
        }
        {{/isBasic}}
        {{#isApiKey}}
        // "Implement API key auth ({{{name}}}) for parameter name '{{{keyParamName}}}'."
        apiKeyAuth("{{{name}}}") {
            validate { apikeyCredential: ApiKeyCredential ->
                when {
                    apikeyCredential.value == "keyboardcat" -> ApiPrincipal(apikeyCredential)
                    else -> null
                }
            }
        }
        {{/isApiKey}}
        {{#isOAuth}}
            {{#bodyAllowed}}
            {{/bodyAllowed}}
            {{^bodyAllowed}}
        oauth("{{name}}") {
            client = HttpClient(Apache)
            providerLookup = { ApplicationAuthProviders["{{{name}}}"] }
            urlProvider = { _ ->
                // TODO: define a callback url here.
                "/"
            }
        }
            {{/bodyAllowed}}
        {{/isOAuth}}
    {{/authMethods}}
    }
    {{/hasAuthMethods}}
    install(Routing) {
    {{#apiInfo}}
    {{#apis}}
    {{#operations}}
        {{classname}}()
    {{/operations}}
    {{/apis}}
    {{/apiInfo}}
    }

{{/generateApis}}
}
