package com.airlock.iam.factor.application.configuration.fido;

import com.airlock.iam.factor.domain.model.fido.FidoAuthenticatorModel;
import com.airlock.iam.factor.domain.model.fido.FidoAuthenticatorModelId;
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.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.PropertyConfigurationException;
import com.airlock.iam.plugin.api.exception.PropertyConstraintViolationException;
import com.airlock.iam.plugin.api.valuereader.StringPropertyValueReader;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

@Plugin(displayName = "FIDO Custom AAGUID Mapping", description = "Describes a FIDO authenticator by mapping its AAGUID to a make and model.")
@PluginLicenseRestriction(moduleAffiliation = "FIDO")
public final class FidoCustomAaguidMappingConfig implements FidoAaguidMappingsConfig {
   @StringProperty(
      description = "The AAGUID (authenticator attestation globally unique identifier) is an opaque identifier chosen by the authenticator manufacturer, indicating the make and model of the authenticator. It may be reported by the FIDO authenticator during registration and is stored in the Airlock IAM database together with the FIDO credential.<p>Note that not all authenticators have an AAGUID. In particular, no U2F authenticators do.</p>",
      optional = false,
      exampleValues = "ee882879-721c-4913-9775-3dfcce97072a",
      displayName = "AAGUID"
   )
   private String aaguid;
   static final String AAGUID_FIELD = "aaguid";
   @StringProperty(
      description = "Describes the FIDO authenticator corresponding to this AAGUID. This typically encompasses the make and model of the FIDO authenticator.",
      exampleValues = {"YubiKey 5 NFC Series", "Windows Hello Hardware Authenticator"},
      maxLength = 200,
      optional = false
   )
   private String description;
   static final String DESCRIPTION_FIELD = "description";

   @ConfigurationValidator
   static void checkAaguidIsValid(PluginConfiguration config, ConfigurationEnvironment env, ConfigurationContext context, Environment validationEnvironment) throws PropertyConfigurationException {
      String configuredAaguid = StringPropertyValueReader.effectiveStringConfigValue(config, "aaguid", env, context);
      if (!FidoAuthenticatorModelId.isValid(configuredAaguid)) {
         throw new PropertyConstraintViolationException(
            "aaguid", config, env, context, "The configured AAGUID is expected to be represented as a UUID (5 hex strings separated by a dash, see RFC 4122)."
         );
      }
   }

   @ConfigurationValidator
   static void checkDescriptionIsValid(
      PluginConfiguration config, ConfigurationEnvironment env, ConfigurationContext context, Environment validationEnvironment
   ) throws PropertyConfigurationException {
      String configuredDescription = StringPropertyValueReader.effectiveStringConfigValue(config, "description", env, context);
      if (!FidoAuthenticatorModel.isValid(configuredDescription)) {
         throw new PropertyConstraintViolationException("description", config, env, context, "Invalid description of a FIDO authenticator.");
      }
   }

   public String getAaguid() {
      return this.aaguid;
   }

   public String getDescription() {
      return this.description;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public FidoCustomAaguidMappingConfig(String aaguid, String description) {
      this.aaguid = aaguid;
      this.description = description;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class FidoCustomAaguidMappingConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String aaguid;
      @SuppressFBWarnings(justification = "generated code")
      private String description;

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

      @SuppressFBWarnings(justification = "generated code")
      public FidoCustomAaguidMappingConfig.FidoCustomAaguidMappingConfigBuilder aaguid(String aaguid) {
         this.aaguid = aaguid;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCustomAaguidMappingConfig.FidoCustomAaguidMappingConfigBuilder description(String description) {
         this.description = description;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCustomAaguidMappingConfig build() {
         return new FidoCustomAaguidMappingConfig(this.aaguid, this.description);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "FidoCustomAaguidMappingConfig.FidoCustomAaguidMappingConfigBuilder(aaguid=" + this.aaguid + ", description=" + this.description + ")";
      }
   }
}
