package com.airlock.iam.common.application.configuration.jwt.signature;

import com.airlock.iam.common.domain.model.jwt.signature.JwsAlgorithmRsa;
import com.airlock.iam.common.domain.model.jwt.signature.SignatureAlgorithm;
import com.airlock.iam.plugin.api.annotation.config.ConfigurationValidator;
import com.airlock.iam.plugin.api.annotation.config.Groups;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.property.EnumProperty;
import com.airlock.iam.plugin.api.annotation.property.GroupProperty;
import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.config.Environment;
import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.api.exception.PropertyConfigurationException;
import com.airlock.iam.plugin.api.valuereader.EnumPropertyValueReader;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.File;

@Plugin(
   description = "<p>Configures RSA based JWT signatures.</p><p>This plugin can be used for JWT signature creation. An RSA based signature is created with a private key and must be validated with the corresponding public key.</p>",
   displayName = "JWT Ticket RSA Signer Settings"
)
@Groups(groupSequence = {"Basic Settings", "Certificate Thumbprints"}, openGroups = "Basic Settings")
public class JwtTicketRsaSignerSettings extends PrivateKeyJwtTicketSignerSettings {
   @EnumProperty(
      description = "The algorithm used for signing. Signing requires an RSA private key, which will be obtained from the configured keystore using the configured properties (alias and password).",
      defaultValue = "RS512",
      optional = true,
      displayName = "RSA Signature Algorithm"
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private JwsAlgorithmRsa rsaSignatureAlgorithm;
   private static final String SIGNATURE_ALGORITHM_NAME = "rsaSignatureAlgorithm";

   public JwtTicketRsaSignerSettings(
      File keystorePath,
      String keystorePassword,
      String privateKeyAlias,
      String privateKeyPassword,
      boolean includeKid,
      boolean addX5tS256HeaderParameter,
      boolean addX5tHeaderParameter,
      JwsAlgorithmRsa rsaSignatureAlgorithm
   ) {
      super(keystorePath, keystorePassword, privateKeyAlias, privateKeyPassword, includeKid, addX5tS256HeaderParameter, addX5tHeaderParameter);
      this.rsaSignatureAlgorithm = rsaSignatureAlgorithm;
   }

   @Override
   protected SignatureAlgorithm signatureAlgorithm() {
      return this.rsaSignatureAlgorithm;
   }

   @ConfigurationValidator(localOnly = true)
   public static void validateConfig(PluginConfiguration pc, ConfigurationEnvironment env, ConfigurationContext context, Environment valenv) throws PropertyConfigurationException {
      if (valenv == Environment.CURRENT_VM) {
         JwsAlgorithmRsa rsaAlgorithm = (JwsAlgorithmRsa)EnumPropertyValueReader.effectiveConfigEnum(pc, "rsaSignatureAlgorithm", env, context);
         validateConfig(pc, env, context, rsaAlgorithm);
      }
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class JwtTicketRsaSignerSettingsBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private File keystorePath;
      @SuppressFBWarnings(justification = "generated code")
      private String keystorePassword;
      @SuppressFBWarnings(justification = "generated code")
      private String privateKeyAlias;
      @SuppressFBWarnings(justification = "generated code")
      private String privateKeyPassword;
      @SuppressFBWarnings(justification = "generated code")
      private boolean includeKid;
      @SuppressFBWarnings(justification = "generated code")
      private boolean addX5tS256HeaderParameter;
      @SuppressFBWarnings(justification = "generated code")
      private boolean addX5tHeaderParameter;
      @SuppressFBWarnings(justification = "generated code")
      private JwsAlgorithmRsa rsaSignatureAlgorithm;

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

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketRsaSignerSettings.JwtTicketRsaSignerSettingsBuilder keystorePath(File keystorePath) {
         this.keystorePath = keystorePath;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketRsaSignerSettings.JwtTicketRsaSignerSettingsBuilder keystorePassword(String keystorePassword) {
         this.keystorePassword = keystorePassword;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketRsaSignerSettings.JwtTicketRsaSignerSettingsBuilder privateKeyAlias(String privateKeyAlias) {
         this.privateKeyAlias = privateKeyAlias;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketRsaSignerSettings.JwtTicketRsaSignerSettingsBuilder privateKeyPassword(String privateKeyPassword) {
         this.privateKeyPassword = privateKeyPassword;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketRsaSignerSettings.JwtTicketRsaSignerSettingsBuilder includeKid(boolean includeKid) {
         this.includeKid = includeKid;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketRsaSignerSettings.JwtTicketRsaSignerSettingsBuilder addX5tS256HeaderParameter(boolean addX5tS256HeaderParameter) {
         this.addX5tS256HeaderParameter = addX5tS256HeaderParameter;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketRsaSignerSettings.JwtTicketRsaSignerSettingsBuilder addX5tHeaderParameter(boolean addX5tHeaderParameter) {
         this.addX5tHeaderParameter = addX5tHeaderParameter;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketRsaSignerSettings.JwtTicketRsaSignerSettingsBuilder rsaSignatureAlgorithm(JwsAlgorithmRsa rsaSignatureAlgorithm) {
         this.rsaSignatureAlgorithm = rsaSignatureAlgorithm;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketRsaSignerSettings build() {
         return new JwtTicketRsaSignerSettings(
            this.keystorePath,
            this.keystorePassword,
            this.privateKeyAlias,
            this.privateKeyPassword,
            this.includeKid,
            this.addX5tS256HeaderParameter,
            this.addX5tHeaderParameter,
            this.rsaSignatureAlgorithm
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "JwtTicketRsaSignerSettings.JwtTicketRsaSignerSettingsBuilder(keystorePath="
            + this.keystorePath
            + ", keystorePassword="
            + this.keystorePassword
            + ", privateKeyAlias="
            + this.privateKeyAlias
            + ", privateKeyPassword="
            + this.privateKeyPassword
            + ", includeKid="
            + this.includeKid
            + ", addX5tS256HeaderParameter="
            + this.addX5tS256HeaderParameter
            + ", addX5tHeaderParameter="
            + this.addX5tHeaderParameter
            + ", rsaSignatureAlgorithm="
            + this.rsaSignatureAlgorithm
            + ")";
      }
   }
}
