package com.airlock.iam.admin.application.configuration.vasco;

import com.airlock.iam.admin.api.domain.model.user.AuthenticationMethods;
import com.airlock.iam.admin.domain.model.token.TokenController;
import com.airlock.iam.core.misc.notification.Notifier;
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.BooleanProperty;
import com.airlock.iam.plugin.api.annotation.property.GroupProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
import com.airlock.iam.plugin.api.annotation.property.StringListProperty;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.Nullable;
import java.util.List;

@Plugin(description = "Configures the token controller to manage Vasco OTP tokens.", displayName = "Vasco OTP Token Controller")
@Groups(groupSequence = {"Basic Settings", "Advanced Token Assignment Settings"}, openGroups = "Basic Settings")
public class VascoOtpTokenControllerConfig implements TokenController {
   @TokenController.TokenControllerId
   public static final String ID = "VASCO_OTP";
   static final String ADVANCED_TOKEN_ASSIGNMENT_SETTINGS = "Advanced Token Assignment Settings";
   public static final String VASCO_OTP_TOKEN_CONTROLLER_DISPLAY_NAME = "Vasco OTP Token Controller";
   @BooleanProperty(
      description = "Set this flag to true to automatically order a letter when a Vasco token is assigned to a user.",
      optional = true,
      defaultValue = "false"
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private boolean autoOrderToken;
   @BooleanProperty(
      description = "If set to true, only enabled tokens are assignable to a user. Otherwise, enabled and disabled tokens can be assigned.",
      displayName = "Only Enabled Tokens Assignable",
      optional = true,
      defaultValue = "true"
   )
   @GroupProperty(groupIdentifier = "Advanced Token Assignment Settings")
   private boolean onlyActiveTokensAssignable;
   @BooleanProperty(description = "Whether it should be allowed to assign the same token to multiple users.", optional = true, defaultValue = "false")
   @GroupProperty(groupIdentifier = "Advanced Token Assignment Settings")
   private boolean assignTokenToMultipleUsers;
   @StringListProperty(
      description = "Token Assignments can be enriched with additional information, e.g. how the token was handed to the user, personally or by mail. This list defines a set of allowed values. The value defined here will be used in two ways: First, it is stored on the persistence. Second, it is used for display: If a resource key prefix is defined below, the prefix concatenated with the value defined here is used to look up a translated text in the string container. Otherwise, the value is displayed directly. If left empty, no additional information can be selected during assignment and no information will be shown.",
      optional = true,
      exampleElements = {"personal", "mail"}
   )
   @GroupProperty(groupIdentifier = "Advanced Token Assignment Settings")
   private List<String> availableAdditionalInformation;
   @BooleanProperty(description = "If set to true, then the additional information field may be set to null.", optional = true, defaultValue = "true")
   @GroupProperty(groupIdentifier = "Advanced Token Assignment Settings")
   private boolean allowEmptyAdditionalInformation;
   @StringProperty(
      description = "If this property is defined, the string values defined for additional information are assumed to be resource keys and are used together with the prefix defined here to display a translated version of the options. If left empty, the additional information strings are displayed as defined above.",
      optional = true
   )
   @GroupProperty(groupIdentifier = "Advanced Token Assignment Settings")
   private String additionalInfoResourceKeyPrefix;
   @BooleanProperty(
      description = "Set this flag to false to prevent this credential from being selected as the next (migration) authentication method.",
      optional = true,
      defaultValue = "true"
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private boolean mayBeSelectedAsNextAuthMethod;
   @PluginProperty(description = "If specified, vasco letters can be generated from the admintool for immediate transmission.", optional = true)
   @GroupProperty(groupIdentifier = "Basic Settings")
   private VascoLetterGenerator vascoLetterGenerator;
   @BooleanProperty(
      description = "If this property is set to true, a warning will be shown within the token assignment dialog. The administrator has to confirm this warning when assigning a token to a user. To define the warning to be displayed, please edit the resource key <b>user.vasco.device.assign.confirm-message</b>.",
      optional = true,
      defaultValue = "false"
   )
   @GroupProperty(groupIdentifier = "Advanced Token Assignment Settings")
   private boolean showWarningWithinTokenAssignmentDialog;
   @BooleanProperty(
      description = "If this property is set to true, a comment field is shown within the token assignment page. To set the label, please edit the resource key <b>assignment.comment-label</b>",
      optional = true,
      defaultValue = "false"
   )
   @GroupProperty(groupIdentifier = "Advanced Token Assignment Settings")
   private boolean enableComment;
   @BooleanProperty(description = "If set to true, then the comment field may be set to null / empty string.", optional = true, defaultValue = "false")
   @GroupProperty(groupIdentifier = "Advanced Token Assignment Settings")
   private boolean allowEmptyComment;
   @PluginProperty(
      description = "If this plugin is configured with a Notifier, the user is notified if an Administrator assigns a Vasco Token. The following variables can be used in the Notifier plugin in the notification template:<br /><ul><li><code>$USERNAME$</code></li><li><code>$SERIALID$</code></li></ul>These variables will be replaced with the actual values when the notification is sent to a user.",
      optional = true
   )
   @GroupProperty(groupIdentifier = "Advanced Token Assignment Settings")
   private Notifier notifier;

   @Override
   public AuthenticationMethods.AuthenticationMethodId getConfiguredId() {
      return AuthenticationMethods.AuthenticationMethodId.authMethodId("VASCO");
   }

   @Override
   public String getTokenControllerId() {
      return "VASCO_OTP";
   }

   public boolean isAutoOrderToken() {
      return this.autoOrderToken;
   }

   public boolean isOnlyActiveTokensAssignable() {
      return this.onlyActiveTokensAssignable;
   }

   public boolean isAssignTokenToMultipleUsers() {
      return this.assignTokenToMultipleUsers;
   }

   public List<String> getAvailableAdditionalInformation() {
      return this.availableAdditionalInformation;
   }

   public boolean isAllowEmptyAdditionalInformation() {
      return this.allowEmptyAdditionalInformation;
   }

   @Nullable
   public String getAdditionalInfoResourceKeyPrefix() {
      return this.additionalInfoResourceKeyPrefix;
   }

   public boolean isMayBeSelectedAsNextAuthMethod() {
      return this.mayBeSelectedAsNextAuthMethod;
   }

   @Nullable
   public VascoLetterGenerator getVascoLetterGenerator() {
      return this.vascoLetterGenerator;
   }

   public boolean isShowWarningWithinTokenAssignmentDialog() {
      return this.showWarningWithinTokenAssignmentDialog;
   }

   public boolean isEnableComment() {
      return this.enableComment;
   }

   public boolean isAllowEmptyComment() {
      return this.allowEmptyComment;
   }

   @Nullable
   public Notifier getNotifier() {
      return this.notifier;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public VascoOtpTokenControllerConfig(
      boolean autoOrderToken,
      boolean onlyActiveTokensAssignable,
      boolean assignTokenToMultipleUsers,
      List<String> availableAdditionalInformation,
      boolean allowEmptyAdditionalInformation,
      String additionalInfoResourceKeyPrefix,
      boolean mayBeSelectedAsNextAuthMethod,
      VascoLetterGenerator vascoLetterGenerator,
      boolean showWarningWithinTokenAssignmentDialog,
      boolean enableComment,
      boolean allowEmptyComment,
      Notifier notifier
   ) {
      this.autoOrderToken = autoOrderToken;
      this.onlyActiveTokensAssignable = onlyActiveTokensAssignable;
      this.assignTokenToMultipleUsers = assignTokenToMultipleUsers;
      this.availableAdditionalInformation = availableAdditionalInformation;
      this.allowEmptyAdditionalInformation = allowEmptyAdditionalInformation;
      this.additionalInfoResourceKeyPrefix = additionalInfoResourceKeyPrefix;
      this.mayBeSelectedAsNextAuthMethod = mayBeSelectedAsNextAuthMethod;
      this.vascoLetterGenerator = vascoLetterGenerator;
      this.showWarningWithinTokenAssignmentDialog = showWarningWithinTokenAssignmentDialog;
      this.enableComment = enableComment;
      this.allowEmptyComment = allowEmptyComment;
      this.notifier = notifier;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class VascoOtpTokenControllerConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private boolean autoOrderToken;
      @SuppressFBWarnings(justification = "generated code")
      private boolean onlyActiveTokensAssignable;
      @SuppressFBWarnings(justification = "generated code")
      private boolean assignTokenToMultipleUsers;
      @SuppressFBWarnings(justification = "generated code")
      private List<String> availableAdditionalInformation;
      @SuppressFBWarnings(justification = "generated code")
      private boolean allowEmptyAdditionalInformation;
      @SuppressFBWarnings(justification = "generated code")
      private String additionalInfoResourceKeyPrefix;
      @SuppressFBWarnings(justification = "generated code")
      private boolean mayBeSelectedAsNextAuthMethod;
      @SuppressFBWarnings(justification = "generated code")
      private VascoLetterGenerator vascoLetterGenerator;
      @SuppressFBWarnings(justification = "generated code")
      private boolean showWarningWithinTokenAssignmentDialog;
      @SuppressFBWarnings(justification = "generated code")
      private boolean enableComment;
      @SuppressFBWarnings(justification = "generated code")
      private boolean allowEmptyComment;
      @SuppressFBWarnings(justification = "generated code")
      private Notifier notifier;

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

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder autoOrderToken(boolean autoOrderToken) {
         this.autoOrderToken = autoOrderToken;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder onlyActiveTokensAssignable(boolean onlyActiveTokensAssignable) {
         this.onlyActiveTokensAssignable = onlyActiveTokensAssignable;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder assignTokenToMultipleUsers(boolean assignTokenToMultipleUsers) {
         this.assignTokenToMultipleUsers = assignTokenToMultipleUsers;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder availableAdditionalInformation(List<String> availableAdditionalInformation) {
         this.availableAdditionalInformation = availableAdditionalInformation;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder allowEmptyAdditionalInformation(boolean allowEmptyAdditionalInformation) {
         this.allowEmptyAdditionalInformation = allowEmptyAdditionalInformation;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder additionalInfoResourceKeyPrefix(String additionalInfoResourceKeyPrefix) {
         this.additionalInfoResourceKeyPrefix = additionalInfoResourceKeyPrefix;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder mayBeSelectedAsNextAuthMethod(boolean mayBeSelectedAsNextAuthMethod) {
         this.mayBeSelectedAsNextAuthMethod = mayBeSelectedAsNextAuthMethod;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder vascoLetterGenerator(VascoLetterGenerator vascoLetterGenerator) {
         this.vascoLetterGenerator = vascoLetterGenerator;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder showWarningWithinTokenAssignmentDialog(
         boolean showWarningWithinTokenAssignmentDialog
      ) {
         this.showWarningWithinTokenAssignmentDialog = showWarningWithinTokenAssignmentDialog;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder enableComment(boolean enableComment) {
         this.enableComment = enableComment;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder allowEmptyComment(boolean allowEmptyComment) {
         this.allowEmptyComment = allowEmptyComment;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder notifier(Notifier notifier) {
         this.notifier = notifier;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public VascoOtpTokenControllerConfig build() {
         return new VascoOtpTokenControllerConfig(
            this.autoOrderToken,
            this.onlyActiveTokensAssignable,
            this.assignTokenToMultipleUsers,
            this.availableAdditionalInformation,
            this.allowEmptyAdditionalInformation,
            this.additionalInfoResourceKeyPrefix,
            this.mayBeSelectedAsNextAuthMethod,
            this.vascoLetterGenerator,
            this.showWarningWithinTokenAssignmentDialog,
            this.enableComment,
            this.allowEmptyComment,
            this.notifier
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "VascoOtpTokenControllerConfig.VascoOtpTokenControllerConfigBuilder(autoOrderToken="
            + this.autoOrderToken
            + ", onlyActiveTokensAssignable="
            + this.onlyActiveTokensAssignable
            + ", assignTokenToMultipleUsers="
            + this.assignTokenToMultipleUsers
            + ", availableAdditionalInformation="
            + this.availableAdditionalInformation
            + ", allowEmptyAdditionalInformation="
            + this.allowEmptyAdditionalInformation
            + ", additionalInfoResourceKeyPrefix="
            + this.additionalInfoResourceKeyPrefix
            + ", mayBeSelectedAsNextAuthMethod="
            + this.mayBeSelectedAsNextAuthMethod
            + ", vascoLetterGenerator="
            + this.vascoLetterGenerator
            + ", showWarningWithinTokenAssignmentDialog="
            + this.showWarningWithinTokenAssignmentDialog
            + ", enableComment="
            + this.enableComment
            + ", allowEmptyComment="
            + this.allowEmptyComment
            + ", notifier="
            + this.notifier
            + ")";
      }
   }
}
