package com.airlock.iam.login.app.misc.oneshot.impl;

import com.airlock.iam.core.domain.model.http.HttpRequest;
import com.airlock.iam.core.domain.model.http.signature.key.HttpSignatureCertificateLoader;
import com.airlock.iam.core.domain.model.http.signature.key.X509CertificateHttpUrlLoader;
import com.airlock.iam.core.misc.util.httpclient.HttpClientConfig;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.lifecycle.AfterConfigActivation;
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;
import java.io.IOException;
import java.security.GeneralSecurityException;

@Plugin(
   description = "Loads the certificate for an HTTP signature keyId. The keyId must be an HTTP(S) URL indicating where the certificate is located. The HTTP response body must contain a PEM, DER or base64-encoded DER X.509 certificate. Certificates will be cached in memory, hence once a certificate is loaded it will remain in the cache until IAM is restarted, a configuration is activated or the maximum cache size is reached.",
   displayName = "HTTP Signature X.509 Certificate URL Loader"
)
public final class HttpSignatureX509CertificateHttpUrlLoaderConfig implements HttpSignatureCertificateLoaderConfig {
   @PluginProperty(
      description = "HTTP client used for the requests. It is recommended to use a trust store containing trusted certificates for HTTPs connections.",
      displayName = "HTTP Client",
      defaultValue = HttpClientConfig.class,
      optional = true
   )
   private HttpClientConfig httpClientConfig;
   @IntegerProperty(
      description = "Defines the maximum number of certificates that reside in the cache. This will limit the memory usage of this feature but may also have a performance trade-off. A regular X.509 certificate has a size of approximately 3kB. If the maximum number of certificates in the cache is reached, certificates that haven't been used recently or very often will be removed from the cache to make space for the newly cached certificate.<p>A maximum cache size of 0 disables the cache.</p>",
      displayName = "Maximum Cache Size",
      exampleValues = {10, 100, 1000, 10000},
      defaultValue = 1000,
      minValue = 0,
      optional = true
   )
   private int maximumCacheSize;
   private X509CertificateHttpUrlLoader certificateLoader;

   public HttpSignatureX509CertificateHttpUrlLoaderConfig(HttpClientConfig httpClientConfig, int maximumCacheSize) {
      this.httpClientConfig = httpClientConfig;
      this.maximumCacheSize = maximumCacheSize;
   }

   @Override
   public HttpSignatureCertificateLoader create(HttpRequest request) {
      return this.certificateLoader;
   }

   @AfterConfigActivation
   void initializeHttpClientAndCertificateLoader() throws GeneralSecurityException, IOException {
      this.certificateLoader = new X509CertificateHttpUrlLoader(this.httpClientConfig.createHttpClient(), this.maximumCacheSize);
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class HttpSignatureX509CertificateHttpUrlLoaderConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private HttpClientConfig httpClientConfig;
      @SuppressFBWarnings(justification = "generated code")
      private int maximumCacheSize;

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

      @SuppressFBWarnings(justification = "generated code")
      public HttpSignatureX509CertificateHttpUrlLoaderConfig.HttpSignatureX509CertificateHttpUrlLoaderConfigBuilder httpClientConfig(
         HttpClientConfig httpClientConfig
      ) {
         this.httpClientConfig = httpClientConfig;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public HttpSignatureX509CertificateHttpUrlLoaderConfig.HttpSignatureX509CertificateHttpUrlLoaderConfigBuilder maximumCacheSize(int maximumCacheSize) {
         this.maximumCacheSize = maximumCacheSize;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public HttpSignatureX509CertificateHttpUrlLoaderConfig build() {
         return new HttpSignatureX509CertificateHttpUrlLoaderConfig(this.httpClientConfig, this.maximumCacheSize);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "HttpSignatureX509CertificateHttpUrlLoaderConfig.HttpSignatureX509CertificateHttpUrlLoaderConfigBuilder(httpClientConfig="
            + this.httpClientConfig
            + ", maximumCacheSize="
            + this.maximumCacheSize
            + ")";
      }
   }
}
