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

import com.airlock.iam.common.domain.model.jwt.signature.JwsAlgorithmEc;
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 EC based JWT signatures.</p><p>This plugin can be used for JWT signature creation. An EC based signature is created with a private key and must be validated with the corresponding public key.</p>",
   displayName = "JWT Ticket EC Signer Settings"
)
@Groups(groupSequence = {"Basic Settings", "Certificate Thumbprints"}, openGroups = "Basic Settings")
public class JwtTicketEcSignerSettings extends PrivateKeyJwtTicketSignerSettings {
   @EnumProperty(
      description = "The algorithm used for signing. Signing requires an EC private key, which will be obtained from the configured keystore using the configured properties (alias and password).<br/><br/>According to the selected algorithm, the private key must be derived from a specific curve:<br/><ul><li>ES512: NIST Curve P521</li><li>ES384: NIST Curve P384</li><li>ES256: NIST Curve P256</li></ul>",
      defaultValue = "ES512",
      optional = true,
      displayName = "EC Signature Algorithm"
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private JwsAlgorithmEc ecSignatureAlgorithm;
   private static final String SIGNATURE_ALGORITHM_NAME = "ecSignatureAlgorithm";

   public JwtTicketEcSignerSettings(
      File keystorePath,
      String keystorePassword,
      String privateKeyAlias,
      String privateKeyPassword,
      boolean includeKid,
      boolean addX5tS256HeaderParameter,
      boolean addX5tHeaderParameter,
      JwsAlgorithmEc ecSignatureAlgorithm
   ) {
      super(keystorePath, keystorePassword, privateKeyAlias, privateKeyPassword, includeKid, addX5tS256HeaderParameter, addX5tHeaderParameter);
      this.ecSignatureAlgorithm = ecSignatureAlgorithm;
   }

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

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

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class JwtTicketEcSignerSettingsBuilder {
      @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 JwsAlgorithmEc ecSignatureAlgorithm;

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

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

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

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

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

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

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

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

      @SuppressFBWarnings(justification = "generated code")
      public JwtTicketEcSignerSettings.JwtTicketEcSignerSettingsBuilder ecSignatureAlgorithm(JwsAlgorithmEc ecSignatureAlgorithm) {
         this.ecSignatureAlgorithm = ecSignatureAlgorithm;
         return this;
      }

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

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