package com.airlock.iam.oauth2.application.configuration;

import com.airlock.iam.core.misc.util.password.hash.RawPasswordHash;
import com.airlock.iam.core.misc.util.password.hash.SHA256PasswordHash;
import com.airlock.iam.oauth2.domain.service.token.OAuth2RandomTokenGenerator;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.license.PluginLicenseRestriction;
import com.airlock.iam.plugin.api.annotation.property.IntegerProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

@Plugin(
   description = "<p>Configuration for OAuth 2.0 token generation, e.g. for generating Authorization Codes.</p>\n<p>This configuration controls how tokens are generated and stored. It allows specifying the length of the\nrandom component of generated tokens and the hash algorithm used to persist tokens securely.</p>",
   displayName = "OAuth 2.0 Token Generator Settings"
)
@PluginLicenseRestriction(moduleAffiliation = "OAuthServer")
public class OAuth2TokenGeneratorConfig {
   public static final String TOKEN_GENERATOR_SETTINGS_DISPLAY_NAME = "OAuth 2.0 Token Generator Settings";
   @IntegerProperty(
      description = "<p>Length (in characters) of the random part in generated OAuth 2.0 Tokens.</p><p>With random tokens, this forms part of the token string itself, for JWT tokens, this string is included in the JWT as \"jti\" claim.</p><p>For security reasons, as recommended by <a target=\"_blank\" href=\"https://tools.ietf.org/html/rfc6749#section-10.10\">RFC 6749</a>, the randomness must be at least 160 bit corresponding to about 28 characters. Overly large values may have a negative performance impact.</p>",
      minValue = 28,
      defaultValue = 40,
      optional = true,
      exampleValues = {30, 50}
   )
   private int tokenRandomPartLength;
   @PluginProperty(
      description = "<p>Hash function used to hash the generated OAuth 2.0 Tokens. Only a random ID and the hash of the token will be persisted.</p><p><b>Warning:</b> When changing this hash, all previously issued tokens will be come invalid!<br><b>Security Warning:</b> A cryptographic hash function should be used.</p>",
      optional = true,
      defaultValue = SHA256PasswordHash.class
   )
   private RawPasswordHash passwordHash;

   public OAuth2RandomTokenGenerator randomTokenGenerator() {
      return OAuth2RandomTokenGenerator.builder().tokenRandomPartLength(this.tokenRandomPartLength).build();
   }

   public int getTokenRandomPartLength() {
      return this.tokenRandomPartLength;
   }

   public RawPasswordHash getPasswordHash() {
      return this.passwordHash;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static OAuth2TokenGeneratorConfig.OAuth2TokenGeneratorConfigBuilder builder() {
      return new OAuth2TokenGeneratorConfig.OAuth2TokenGeneratorConfigBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public OAuth2TokenGeneratorConfig() {
   }

   @SuppressFBWarnings(justification = "generated code")
   public OAuth2TokenGeneratorConfig(int tokenRandomPartLength, RawPasswordHash passwordHash) {
      this.tokenRandomPartLength = tokenRandomPartLength;
      this.passwordHash = passwordHash;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class OAuth2TokenGeneratorConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private int tokenRandomPartLength;
      @SuppressFBWarnings(justification = "generated code")
      private RawPasswordHash passwordHash;

      @SuppressFBWarnings(justification = "generated code")
      OAuth2TokenGeneratorConfigBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public OAuth2TokenGeneratorConfig.OAuth2TokenGeneratorConfigBuilder tokenRandomPartLength(int tokenRandomPartLength) {
         this.tokenRandomPartLength = tokenRandomPartLength;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OAuth2TokenGeneratorConfig.OAuth2TokenGeneratorConfigBuilder passwordHash(RawPasswordHash passwordHash) {
         this.passwordHash = passwordHash;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OAuth2TokenGeneratorConfig build() {
         return new OAuth2TokenGeneratorConfig(this.tokenRandomPartLength, this.passwordHash);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "OAuth2TokenGeneratorConfig.OAuth2TokenGeneratorConfigBuilder(tokenRandomPartLength="
            + this.tokenRandomPartLength
            + ", passwordHash="
            + this.passwordHash
            + ")";
      }
   }
}
