package {{configPackage}}

{{#authMethods}}
{{#isBasicBasic}}
import feign.auth.BasicAuthRequestInterceptor
{{/isBasicBasic}}
{{#-first}}
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
{{/-first}}
{{#isOAuth}}
import org.springframework.boot.context.properties.ConfigurationProperties
{{/isOAuth}}
{{/authMethods}}
import org.springframework.boot.context.properties.EnableConfigurationProperties
{{#authMethods}}
{{#-first}}
import org.springframework.context.annotation.Bean
{{/-first}}
{{/authMethods}}
import org.springframework.context.annotation.Configuration
{{#authMethods}}
{{#isOAuth}}
import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext
import org.springframework.security.oauth2.client.OAuth2ClientContext
{{#isApplication}}
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails
{{/isApplication}}
{{#isCode}}
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails
{{/isCode}}
{{#isImplicit}}
import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails
{{/isImplicit}}
{{#isPassword}}
import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails
{{/isPassword}}
{{/isOAuth}}
{{/authMethods}}

@Configuration
@EnableConfigurationProperties
class ClientConfiguration {

    {{#authMethods}}
    {{#isBasicBasic}}
    @Value("\${{openbrace}}{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.username:{{closebrace}}")
    private lateinit var {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Username: String

    @Value("\${{openbrace}}{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.password:{{closebrace}}")
    private lateinit var {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Password: String

    @Bean
    @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.username")
    fun {{{name}}}RequestInterceptor(): BasicAuthRequestInterceptor {
      return BasicAuthRequestInterceptor(this.{{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Username, this.{{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Password)
    }

    {{/isBasicBasic}}
    {{#isApiKey}}
    @Value("\${{openbrace}}{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.key:{{closebrace}}")
    private lateinit var {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Key: String

    @Bean
    @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.key")
    fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}RequestInterceptor(): ApiKeyRequestInterceptor {
        return ApiKeyRequestInterceptor({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{{keyParamName}}}", this.{{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Key)
    }

    {{/isApiKey}}
    {{#isOAuth}}
    @Bean
    @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id")
    fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}RequestInterceptor(oAuth2ClientContext: OAuth2ClientContext): OAuth2FeignRequestInterceptor {
        return OAuth2FeignRequestInterceptor(oAuth2ClientContext, {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails())
    }

    @Bean
    @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id")
    fun oAuth2ClientContext(): OAuth2ClientContext {
        return DefaultOAuth2ClientContext()
    }

    {{#isCode}}
    @Bean
    @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id")
    @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}")
    fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails(): AuthorizationCodeResourceDetails {
        val details = AuthorizationCodeResourceDetails()
        details.accessTokenUri = "{{{tokenUrl}}}"
        details.userAuthorizationUri = "{{{authorizationUrl}}}"
        return details
    }

    {{/isCode}}
    {{#isPassword}}
    @Bean
    @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id")
    @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}")
    fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails(): ResourceOwnerPasswordResourceDetails {
        val details = ResourceOwnerPasswordResourceDetails()
        details.accessTokenUri = "{{{tokenUrl}}}"
        return details
    }

    {{/isPassword}}
    {{#isApplication}}
    @Bean
    @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id")
    @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}")
    fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails(): ClientCredentialsResourceDetails {
        val details = ClientCredentialsResourceDetails()
        details.accessTokenUri = "{{{tokenUrl}}}"
        return details
    }

    {{/isApplication}}
    {{#isImplicit}}
    @Bean
    @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id")
    @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}")
    fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails(): ImplicitResourceDetails {
        val details = ImplicitResourceDetails()
        details.userAuthorizationUri= "{{{authorizationUrl}}}"
        return details
    }

    {{/isImplicit}}
    {{/isOAuth}}
    {{/authMethods}}
}
