package com.airlock.iam.factor.domain.model.fido;

import com.airlock.iam.factor.domain.model.fido.registration.FidoAttestationType;
import com.airlock.iam.factor.domain.model.fido.registration.FidoAuthenticatorType;
import com.airlock.iam.factor.domain.model.fido.registration.FidoUserVerificationPreference;
import com.airlock.iam.factor.domain.model.fido.registration.ResidentKeyRequirement;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import lombok.NonNull;

public final class FidoCredentialRegistrationSettings {
   @NonNull
   private final FidoRelyingPartyName relyingPartyName;
   @NonNull
   private final FidoCredentialName credentialName;
   @NonNull
   private final List<SupportedCoseAlgorithmIdentifier> preferredAlgorithms;
   @NonNull
   private final FidoTimeout registrationTimeout;
   @NonNull
   private final FidoAuthenticatorType authenticatorType;
   @NonNull
   private final ResidentKeyRequirement residentKey;
   @NonNull
   private final FidoUserVerificationPreference userVerification;
   @NonNull
   private final FidoAttestationType attestationType;
   private final boolean autoGenerateDisplayName;
   private final boolean preventDoubleRegistration;

   public boolean effectiveRequireResidentKey() {
      return this.residentKey == ResidentKeyRequirement.REQUIRED;
   }

   @SuppressFBWarnings(justification = "generated code")
   FidoCredentialRegistrationSettings(
      @NonNull FidoRelyingPartyName relyingPartyName,
      @NonNull FidoCredentialName credentialName,
      @NonNull List<SupportedCoseAlgorithmIdentifier> preferredAlgorithms,
      @NonNull FidoTimeout registrationTimeout,
      @NonNull FidoAuthenticatorType authenticatorType,
      @NonNull ResidentKeyRequirement residentKey,
      @NonNull FidoUserVerificationPreference userVerification,
      @NonNull FidoAttestationType attestationType,
      boolean autoGenerateDisplayName,
      boolean preventDoubleRegistration
   ) {
      if (relyingPartyName == null) {
         throw new NullPointerException("relyingPartyName is marked non-null but is null");
      }

      if (credentialName == null) {
         throw new NullPointerException("credentialName is marked non-null but is null");
      }

      if (preferredAlgorithms == null) {
         throw new NullPointerException("preferredAlgorithms is marked non-null but is null");
      }

      if (registrationTimeout == null) {
         throw new NullPointerException("registrationTimeout is marked non-null but is null");
      }

      if (authenticatorType == null) {
         throw new NullPointerException("authenticatorType is marked non-null but is null");
      }

      if (residentKey == null) {
         throw new NullPointerException("residentKey is marked non-null but is null");
      }

      if (userVerification == null) {
         throw new NullPointerException("userVerification is marked non-null but is null");
      }

      if (attestationType == null) {
         throw new NullPointerException("attestationType is marked non-null but is null");
      }

      this.relyingPartyName = relyingPartyName;
      this.credentialName = credentialName;
      this.preferredAlgorithms = preferredAlgorithms;
      this.registrationTimeout = registrationTimeout;
      this.authenticatorType = authenticatorType;
      this.residentKey = residentKey;
      this.userVerification = userVerification;
      this.attestationType = attestationType;
      this.autoGenerateDisplayName = autoGenerateDisplayName;
      this.preventDoubleRegistration = preventDoubleRegistration;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder toBuilder() {
      FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder builder = new FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder()
         .relyingPartyName(this.relyingPartyName)
         .credentialName(this.credentialName)
         .registrationTimeout(this.registrationTimeout)
         .authenticatorType(this.authenticatorType)
         .residentKey(this.residentKey)
         .userVerification(this.userVerification)
         .attestationType(this.attestationType)
         .autoGenerateDisplayName(this.autoGenerateDisplayName)
         .preventDoubleRegistration(this.preventDoubleRegistration);
      if (this.preferredAlgorithms != null) {
         builder.preferredAlgorithms(this.preferredAlgorithms);
      }

      return builder;
   }

   @NonNull
   @SuppressFBWarnings(justification = "generated code")
   public FidoRelyingPartyName getRelyingPartyName() {
      return this.relyingPartyName;
   }

   @NonNull
   @SuppressFBWarnings(justification = "generated code")
   public FidoCredentialName getCredentialName() {
      return this.credentialName;
   }

   @NonNull
   @SuppressFBWarnings(justification = "generated code")
   public List<SupportedCoseAlgorithmIdentifier> getPreferredAlgorithms() {
      return this.preferredAlgorithms;
   }

   @NonNull
   @SuppressFBWarnings(justification = "generated code")
   public FidoTimeout getRegistrationTimeout() {
      return this.registrationTimeout;
   }

   @NonNull
   @SuppressFBWarnings(justification = "generated code")
   public FidoAuthenticatorType getAuthenticatorType() {
      return this.authenticatorType;
   }

   @NonNull
   @SuppressFBWarnings(justification = "generated code")
   public ResidentKeyRequirement getResidentKey() {
      return this.residentKey;
   }

   @NonNull
   @SuppressFBWarnings(justification = "generated code")
   public FidoUserVerificationPreference getUserVerification() {
      return this.userVerification;
   }

   @NonNull
   @SuppressFBWarnings(justification = "generated code")
   public FidoAttestationType getAttestationType() {
      return this.attestationType;
   }

   @SuppressFBWarnings(justification = "generated code")
   public boolean isAutoGenerateDisplayName() {
      return this.autoGenerateDisplayName;
   }

   @SuppressFBWarnings(justification = "generated code")
   public boolean isPreventDoubleRegistration() {
      return this.preventDoubleRegistration;
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public boolean equals(Object o) {
      if (o == this) {
         return true;
      } else if (!(o instanceof FidoCredentialRegistrationSettings other)) {
         return false;
      } else {
         if (this.autoGenerateDisplayName != other.autoGenerateDisplayName) {
            return false;
         }

         if (this.preventDoubleRegistration != other.preventDoubleRegistration) {
            return false;
         }

         Object this$relyingPartyName = this.relyingPartyName;
         Object other$relyingPartyName = other.relyingPartyName;
         if (this$relyingPartyName == null ? other$relyingPartyName == null : this$relyingPartyName.equals(other$relyingPartyName)) {
            Object this$credentialName = this.credentialName;
            Object other$credentialName = other.credentialName;
            if (this$credentialName == null ? other$credentialName == null : this$credentialName.equals(other$credentialName)) {
               Object this$preferredAlgorithms = this.preferredAlgorithms;
               Object other$preferredAlgorithms = other.preferredAlgorithms;
               if (this$preferredAlgorithms == null ? other$preferredAlgorithms == null : this$preferredAlgorithms.equals(other$preferredAlgorithms)) {
                  Object this$registrationTimeout = this.registrationTimeout;
                  Object other$registrationTimeout = other.registrationTimeout;
                  if (this$registrationTimeout == null ? other$registrationTimeout == null : this$registrationTimeout.equals(other$registrationTimeout)) {
                     Object this$authenticatorType = this.authenticatorType;
                     Object other$authenticatorType = other.authenticatorType;
                     if (this$authenticatorType == null ? other$authenticatorType == null : this$authenticatorType.equals(other$authenticatorType)) {
                        Object this$residentKey = this.residentKey;
                        Object other$residentKey = other.residentKey;
                        if (this$residentKey == null ? other$residentKey == null : this$residentKey.equals(other$residentKey)) {
                           Object this$userVerification = this.userVerification;
                           Object other$userVerification = other.userVerification;
                           if (this$userVerification == null ? other$userVerification == null : this$userVerification.equals(other$userVerification)) {
                              Object this$attestationType = this.attestationType;
                              Object other$attestationType = other.attestationType;
                              return this$attestationType == null ? other$attestationType == null : this$attestationType.equals(other$attestationType);
                           } else {
                              return false;
                           }
                        } else {
                           return false;
                        }
                     } else {
                        return false;
                     }
                  } else {
                     return false;
                  }
               } else {
                  return false;
               }
            } else {
               return false;
            }
         } else {
            return false;
         }
      }
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public int hashCode() {
      int PRIME = 59;
      int result = 1;
      result = result * 59 + (this.autoGenerateDisplayName ? 79 : 97);
      result = result * 59 + (this.preventDoubleRegistration ? 79 : 97);
      Object $relyingPartyName = this.relyingPartyName;
      result = result * 59 + ($relyingPartyName == null ? 43 : $relyingPartyName.hashCode());
      Object $credentialName = this.credentialName;
      result = result * 59 + ($credentialName == null ? 43 : $credentialName.hashCode());
      Object $preferredAlgorithms = this.preferredAlgorithms;
      result = result * 59 + ($preferredAlgorithms == null ? 43 : $preferredAlgorithms.hashCode());
      Object $registrationTimeout = this.registrationTimeout;
      result = result * 59 + ($registrationTimeout == null ? 43 : $registrationTimeout.hashCode());
      Object $authenticatorType = this.authenticatorType;
      result = result * 59 + ($authenticatorType == null ? 43 : $authenticatorType.hashCode());
      Object $residentKey = this.residentKey;
      result = result * 59 + ($residentKey == null ? 43 : $residentKey.hashCode());
      Object $userVerification = this.userVerification;
      result = result * 59 + ($userVerification == null ? 43 : $userVerification.hashCode());
      Object $attestationType = this.attestationType;
      return result * 59 + ($attestationType == null ? 43 : $attestationType.hashCode());
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public String toString() {
      return "FidoCredentialRegistrationSettings(relyingPartyName="
         + this.getRelyingPartyName()
         + ", credentialName="
         + this.getCredentialName()
         + ", preferredAlgorithms="
         + this.getPreferredAlgorithms()
         + ", registrationTimeout="
         + this.getRegistrationTimeout()
         + ", authenticatorType="
         + this.getAuthenticatorType()
         + ", residentKey="
         + this.getResidentKey()
         + ", userVerification="
         + this.getUserVerification()
         + ", attestationType="
         + this.getAttestationType()
         + ", autoGenerateDisplayName="
         + this.isAutoGenerateDisplayName()
         + ", preventDoubleRegistration="
         + this.isPreventDoubleRegistration()
         + ")";
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class FidoCredentialRegistrationSettingsBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private FidoRelyingPartyName relyingPartyName;
      @SuppressFBWarnings(justification = "generated code")
      private FidoCredentialName credentialName;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<SupportedCoseAlgorithmIdentifier> preferredAlgorithms;
      @SuppressFBWarnings(justification = "generated code")
      private FidoTimeout registrationTimeout;
      @SuppressFBWarnings(justification = "generated code")
      private FidoAuthenticatorType authenticatorType;
      @SuppressFBWarnings(justification = "generated code")
      private ResidentKeyRequirement residentKey;
      @SuppressFBWarnings(justification = "generated code")
      private FidoUserVerificationPreference userVerification;
      @SuppressFBWarnings(justification = "generated code")
      private FidoAttestationType attestationType;
      @SuppressFBWarnings(justification = "generated code")
      private boolean autoGenerateDisplayName;
      @SuppressFBWarnings(justification = "generated code")
      private boolean preventDoubleRegistration;

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

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder relyingPartyName(@NonNull FidoRelyingPartyName relyingPartyName) {
         if (relyingPartyName == null) {
            throw new NullPointerException("relyingPartyName is marked non-null but is null");
         }

         this.relyingPartyName = relyingPartyName;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder credentialName(@NonNull FidoCredentialName credentialName) {
         if (credentialName == null) {
            throw new NullPointerException("credentialName is marked non-null but is null");
         }

         this.credentialName = credentialName;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder preferredAlgorithm(
         SupportedCoseAlgorithmIdentifier preferredAlgorithm
      ) {
         if (this.preferredAlgorithms == null) {
            this.preferredAlgorithms = new ArrayList<>();
         }

         this.preferredAlgorithms.add(preferredAlgorithm);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder preferredAlgorithms(
         Collection<? extends SupportedCoseAlgorithmIdentifier> preferredAlgorithms
      ) {
         if (preferredAlgorithms == null) {
            throw new NullPointerException("preferredAlgorithms cannot be null");
         }

         if (this.preferredAlgorithms == null) {
            this.preferredAlgorithms = new ArrayList<>();
         }

         this.preferredAlgorithms.addAll(preferredAlgorithms);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder clearPreferredAlgorithms() {
         if (this.preferredAlgorithms != null) {
            this.preferredAlgorithms.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder registrationTimeout(@NonNull FidoTimeout registrationTimeout) {
         if (registrationTimeout == null) {
            throw new NullPointerException("registrationTimeout is marked non-null but is null");
         }

         this.registrationTimeout = registrationTimeout;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder authenticatorType(@NonNull FidoAuthenticatorType authenticatorType) {
         if (authenticatorType == null) {
            throw new NullPointerException("authenticatorType is marked non-null but is null");
         }

         this.authenticatorType = authenticatorType;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder residentKey(@NonNull ResidentKeyRequirement residentKey) {
         if (residentKey == null) {
            throw new NullPointerException("residentKey is marked non-null but is null");
         }

         this.residentKey = residentKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder userVerification(
         @NonNull FidoUserVerificationPreference userVerification
      ) {
         if (userVerification == null) {
            throw new NullPointerException("userVerification is marked non-null but is null");
         }

         this.userVerification = userVerification;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder attestationType(@NonNull FidoAttestationType attestationType) {
         if (attestationType == null) {
            throw new NullPointerException("attestationType is marked non-null but is null");
         }

         this.attestationType = attestationType;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder autoGenerateDisplayName(boolean autoGenerateDisplayName) {
         this.autoGenerateDisplayName = autoGenerateDisplayName;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder preventDoubleRegistration(boolean preventDoubleRegistration) {
         this.preventDoubleRegistration = preventDoubleRegistration;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FidoCredentialRegistrationSettings build() {
         return new FidoCredentialRegistrationSettings(
            this.relyingPartyName,
            this.credentialName,
            switch (this.preferredAlgorithms == null ? 0 : this.preferredAlgorithms.size()) {
               case 0 -> Collections.emptyList();
               case 1 -> Collections.singletonList(this.preferredAlgorithms.get(0));
               default -> Collections.unmodifiableList(new ArrayList<>(this.preferredAlgorithms));
            },
            this.registrationTimeout,
            this.authenticatorType,
            this.residentKey,
            this.userVerification,
            this.attestationType,
            this.autoGenerateDisplayName,
            this.preventDoubleRegistration
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "FidoCredentialRegistrationSettings.FidoCredentialRegistrationSettingsBuilder(relyingPartyName="
            + this.relyingPartyName
            + ", credentialName="
            + this.credentialName
            + ", preferredAlgorithms="
            + this.preferredAlgorithms
            + ", registrationTimeout="
            + this.registrationTimeout
            + ", authenticatorType="
            + this.authenticatorType
            + ", residentKey="
            + this.residentKey
            + ", userVerification="
            + this.userVerification
            + ", attestationType="
            + this.attestationType
            + ", autoGenerateDisplayName="
            + this.autoGenerateDisplayName
            + ", preventDoubleRegistration="
            + this.preventDoubleRegistration
            + ")";
      }
   }
}
