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

import com.airlock.iam.core.domain.model.http.digest.HttpDigestVerificationLogger;
import com.airlock.iam.core.domain.model.http.digest.HttpDigestVerifier;
import com.airlock.iam.core.domain.model.http.digest.HttpInstanceDigestAlgorithm;
import com.airlock.iam.core.domain.model.http.digest.HttpInstanceDigestRequestVerifier;
import com.airlock.iam.elog.api.ELoggerFactory;
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.GroupProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginListProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Plugin(
   description = "Verifies the HTTP Instance Digest according to <a href=\"https://tools.ietf.org/html/rfc3230\">RFC 3230</a>.",
   displayName = "HTTP Instance Digest Verification"
)
@Groups(groupSequence = {"Verification", "Audit Logging"}, openGroups = "Verification")
public final class HttpInstanceDigestVerificationConfig {
   static final String VERIFICATION = "Verification";
   static final String AUDIT_LOGGING = "Audit Logging";
   @PluginListProperty(description = "Allowed algorithms that the digest must use.", optional = false, minElements = 1)
   @GroupProperty(groupIdentifier = "Verification")
   private List<HttpInstanceDigestAlgorithmConfig> allowedAlgorithms;
   @PluginProperty(
      description = "Enables logging of digest verification information. Successfully verified digests and request body contents will be logged. This allows to verify digests at a later point in time.<p><b>Security Warning</b>: Request bodies often contain sensitive information and should therefore not be logged. If this feature is enabled, it is highly recommended that these logs are redirected to a special destination using the Logger Name.</p>",
      optional = true
   )
   @GroupProperty(groupIdentifier = "Audit Logging")
   private HttpSignatureAuditLoggerConfig auditLogger;

   public HttpInstanceDigestRequestVerifier verifier() {
      return new HttpInstanceDigestRequestVerifier(this.digestVerifier());
   }

   private HttpDigestVerifier digestVerifier() {
      return this.auditLogger != null
         ? HttpDigestVerifier.httpDigestVerifier(this.allowedAlgorithms(), this.logger())
         : HttpDigestVerifier.httpDigestVerifier(this.allowedAlgorithms());
   }

   private List<HttpInstanceDigestAlgorithm> allowedAlgorithms() {
      return this.allowedAlgorithms.stream().map(HttpInstanceDigestAlgorithmConfig::algorithm).collect(Collectors.toList());
   }

   private HttpDigestVerificationLogger logger() {
      Optional<String> loggerName = this.auditLogger.loggerName();
      return loggerName.isPresent()
         ? new HttpDigestVerificationLogger(ELoggerFactory.getLogger(loggerName.get()))
         : new HttpDigestVerificationLogger(ELoggerFactory.getLogger(HttpDigestVerificationLogger.class));
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public HttpInstanceDigestVerificationConfig(List<HttpInstanceDigestAlgorithmConfig> allowedAlgorithms, HttpSignatureAuditLoggerConfig auditLogger) {
      this.allowedAlgorithms = allowedAlgorithms;
      this.auditLogger = auditLogger;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class HttpInstanceDigestVerificationConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private List<HttpInstanceDigestAlgorithmConfig> allowedAlgorithms;
      @SuppressFBWarnings(justification = "generated code")
      private HttpSignatureAuditLoggerConfig auditLogger;

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

      @SuppressFBWarnings(justification = "generated code")
      public HttpInstanceDigestVerificationConfig.HttpInstanceDigestVerificationConfigBuilder allowedAlgorithms(
         List<HttpInstanceDigestAlgorithmConfig> allowedAlgorithms
      ) {
         this.allowedAlgorithms = allowedAlgorithms;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public HttpInstanceDigestVerificationConfig.HttpInstanceDigestVerificationConfigBuilder auditLogger(HttpSignatureAuditLoggerConfig auditLogger) {
         this.auditLogger = auditLogger;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public HttpInstanceDigestVerificationConfig build() {
         return new HttpInstanceDigestVerificationConfig(this.allowedAlgorithms, this.auditLogger);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "HttpInstanceDigestVerificationConfig.HttpInstanceDigestVerificationConfigBuilder(allowedAlgorithms="
            + this.allowedAlgorithms
            + ", auditLogger="
            + this.auditLogger
            + ")";
      }
   }
}
