package com.airlock.iam.login.app.misc.configuration.saml;

import com.airlock.iam.core.misc.plugin.config.validation.KeystoreValidator;
import com.airlock.iam.core.misc.plugin.config.validation.KeystoreValidatorHelper;
import com.airlock.iam.plugin.api.annotation.config.ConfigurationValidator;
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.FileProperty;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
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.ConfigurationException;
import com.airlock.iam.saml2.application.configuration.SamlFederationConfig;
import com.sun.identity.saml.xmlsig.JKSKeyProvider;
import com.sun.identity.saml.xmlsig.KeyProvider;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.File;

@Plugin(description = "SAML2 Signature Provider for XML signatures using a keystore on the file system.", displayName = "SAML XML Signature Provider")
@PluginLicenseRestriction(moduleAffiliation = {"SamlIdp", "SamlSp"})
public class SamlXmlSignatureProvider implements SamlFederationConfig.ISamlKeystoreProvider {
   private static final Class<JKSKeyProvider> KEYSTORE_PROVIDER_CLASS = JKSKeyProvider.class;
   @FileProperty(
      description = "The keystore used for SAML2 XML signatures and encryption.",
      optional = false,
      isFile = true,
      assureReadable = true,
      assureExistence = true,
      exampleValues = "saml2/keystore.jks"
   )
   private File keystore;
   private static final String KEYSTORE_PROPERTY = "keystore";
   @StringProperty(description = "The keystore type.", optional = true, allowedValues = {"jks", "pkcs12"}, defaultValue = "jks")
   private String keystoreType;
   private static final String KEYSTORE_TYPE_PROPERTY = "keystoreType";
   @FileProperty(
      description = "The file containing the keystore password.<br/>The contents are decoded using the \"Password Decoder\" in the \"SAML Federation Config\".",
      optional = false,
      isFile = true,
      assureReadable = true,
      assureExistence = true,
      exampleValues = "saml2/.storepass"
   )
   private File keystorePasswordFile;
   private static final String KEYSTORE_PASSWORD_FILE_PROPERTY = "keystorePasswordFile";
   @FileProperty(
      description = "The file containing the private key password.<br/>The contents are decoded using the \"Password Decoder\" in the \"SAML Federation Config\".",
      optional = false,
      isFile = true,
      assureReadable = true,
      assureExistence = true,
      exampleValues = "saml2/.keypass"
   )
   private File keystorePrivateKeyPasswordFile;

   @ConfigurationValidator(localOnly = true)
   public static void checkKeystoreDependencies(
      PluginConfiguration conf, ConfigurationEnvironment env, ConfigurationContext context, Environment validationEnvironment
   ) throws ConfigurationException {
      if (validationEnvironment == Environment.CURRENT_VM) {
         KeystoreValidatorHelper validator = KeystoreValidator.getKeystoreValidator("keystore", "keystorePasswordFile", "keystoreType", conf, env, context);
         validator.validateKeystore();
      }
   }

   @Override
   public File getKeystore() {
      return this.keystore;
   }

   @Override
   public String getKeystoreType() {
      return this.keystoreType;
   }

   @Override
   public File getKeystorePasswordFile() {
      return this.keystorePasswordFile;
   }

   @Override
   public File getKeystorePrivateKeyPasswordFile() {
      return this.keystorePrivateKeyPasswordFile;
   }

   @Override
   public Class<? extends KeyProvider> getImplementationClass() {
      return KEYSTORE_PROVIDER_CLASS;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public SamlXmlSignatureProvider(File keystore, String keystoreType, File keystorePasswordFile, File keystorePrivateKeyPasswordFile) {
      this.keystore = keystore;
      this.keystoreType = keystoreType;
      this.keystorePasswordFile = keystorePasswordFile;
      this.keystorePrivateKeyPasswordFile = keystorePrivateKeyPasswordFile;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class SamlXmlSignatureProviderBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private File keystore;
      @SuppressFBWarnings(justification = "generated code")
      private String keystoreType;
      @SuppressFBWarnings(justification = "generated code")
      private File keystorePasswordFile;
      @SuppressFBWarnings(justification = "generated code")
      private File keystorePrivateKeyPasswordFile;

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

      @SuppressFBWarnings(justification = "generated code")
      public SamlXmlSignatureProvider.SamlXmlSignatureProviderBuilder keystore(File keystore) {
         this.keystore = keystore;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SamlXmlSignatureProvider.SamlXmlSignatureProviderBuilder keystoreType(String keystoreType) {
         this.keystoreType = keystoreType;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SamlXmlSignatureProvider.SamlXmlSignatureProviderBuilder keystorePasswordFile(File keystorePasswordFile) {
         this.keystorePasswordFile = keystorePasswordFile;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SamlXmlSignatureProvider.SamlXmlSignatureProviderBuilder keystorePrivateKeyPasswordFile(File keystorePrivateKeyPasswordFile) {
         this.keystorePrivateKeyPasswordFile = keystorePrivateKeyPasswordFile;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SamlXmlSignatureProvider build() {
         return new SamlXmlSignatureProvider(this.keystore, this.keystoreType, this.keystorePasswordFile, this.keystorePrivateKeyPasswordFile);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "SamlXmlSignatureProvider.SamlXmlSignatureProviderBuilder(keystore="
            + this.keystore
            + ", keystoreType="
            + this.keystoreType
            + ", keystorePasswordFile="
            + this.keystorePasswordFile
            + ", keystorePrivateKeyPasswordFile="
            + this.keystorePrivateKeyPasswordFile
            + ")";
      }
   }
}
