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

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.persistency.TokenListPersister;
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.license.PluginPropertyLicenseRestriction;
import com.airlock.iam.plugin.api.annotation.property.BooleanProperty;
import com.airlock.iam.plugin.api.annotation.property.IntegerProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.time.Duration;
import java.util.Optional;

@Plugin(description = "Credential controller to manage matrix cards in the admintool.")
@PluginLicenseRestriction(moduleAffiliation = "Matrixcard")
public final class MatrixTokenController implements TokenController {
   public static final String ID = "MATRIX";
   @TokenController.TokenControllerId
   @StringProperty(
      description = "Identifier for the credential. This is used as value in the authentication method field in the persistence layer. Make sure this value is the same (for the same credential) in all Airlock IAM components.<p>Make sure the identifier is unique among all configured credential controllers.</p><p>The identifier is also used as key to translate the display name of this credential controller. The key is assembled as follows: <code>edituserpage.cred.XYZ.title</code> (where XYZ is the identifier).</p>",
      optional = true,
      defaultValue = "MATRIX",
      suggestedValues = {"MATRIX", "GRIDCARD", "TAN", "TOKENLIST"}
   )
   private String identifier;
   @BooleanProperty(
      description = "Set this flag to true to automatically order a matrix card when it is added to a user.",
      optional = true,
      defaultValue = "false"
   )
   private boolean autoOrder;
   @BooleanProperty(
      description = "Set this flag to true to automatically order a matrix card if the user is created.",
      optional = true,
      defaultValue = "false"
   )
   private boolean autoOrderForNewUsers;
   @BooleanProperty(
      description = "Set this flag to false to prevent this credential from being selected as active authentication method.",
      optional = true,
      defaultValue = "true"
   )
   private boolean mayBeSelectedAsAuthMethod;
   @BooleanProperty(
      description = "Set this flag to false to prevent this credential from being selected as the next (migration) authentication method.",
      optional = true,
      defaultValue = "true"
   )
   @PluginPropertyLicenseRestriction(moduleAffiliation = "TokenSelfService")
   private boolean mayBeSelectedAsNextAuthMethod;
   @PluginProperty(
      description = "The token list persister used to read and write matrix card data from some persistence layer (e.g. a database or directory).",
      optional = false
   )
   private TokenListPersister tokenListPersister;
   @IntegerProperty(
      description = "The number of days a token list is considered valid for. This number is used to calculate the expiration date of a token list based on the token list generation date.<p>Make sure to use the same value here as in other Airlock IAM components.</p><p>If this property is not defined, no token list expiry date is displayed.</p>",
      optional = true,
      exampleValues = {180, 365},
      minValue = 1
   )
   private Integer validityDays;
   @PluginProperty(description = "If specified, matrix cards can be generated from the admintool.", optional = true)
   private MatrixCardGeneratorConfig matrixCardGenerator;

   public Optional<Duration> getValidity() {
      return Optional.ofNullable(this.validityDays != null ? Duration.ofDays(this.validityDays.intValue()) : null);
   }

   public Optional<MatrixCardGeneratorConfig> getMatrixCardGeneratorConfig() {
      return Optional.ofNullable(this.matrixCardGenerator);
   }

   @Override
   public AuthenticationMethods.AuthenticationMethodId getConfiguredId() {
      return AuthenticationMethods.AuthenticationMethodId.authMethodId(this.identifier);
   }

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

   public boolean isAutoOrder() {
      return this.autoOrder;
   }

   public boolean isAutoOrderForNewUsers() {
      return this.autoOrderForNewUsers;
   }

   public boolean mayBeSelectedAsAuthMethod() {
      return this.mayBeSelectedAsAuthMethod;
   }

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

   public TokenListPersister getTokenListPersister() {
      return this.tokenListPersister;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public MatrixTokenController(
      String identifier,
      boolean autoOrder,
      boolean autoOrderForNewUsers,
      boolean mayBeSelectedAsAuthMethod,
      boolean mayBeSelectedAsNextAuthMethod,
      TokenListPersister tokenListPersister,
      Integer validityDays,
      MatrixCardGeneratorConfig matrixCardGenerator
   ) {
      this.identifier = identifier;
      this.autoOrder = autoOrder;
      this.autoOrderForNewUsers = autoOrderForNewUsers;
      this.mayBeSelectedAsAuthMethod = mayBeSelectedAsAuthMethod;
      this.mayBeSelectedAsNextAuthMethod = mayBeSelectedAsNextAuthMethod;
      this.tokenListPersister = tokenListPersister;
      this.validityDays = validityDays;
      this.matrixCardGenerator = matrixCardGenerator;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class MatrixTokenControllerBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String identifier;
      @SuppressFBWarnings(justification = "generated code")
      private boolean autoOrder;
      @SuppressFBWarnings(justification = "generated code")
      private boolean autoOrderForNewUsers;
      @SuppressFBWarnings(justification = "generated code")
      private boolean mayBeSelectedAsAuthMethod;
      @SuppressFBWarnings(justification = "generated code")
      private boolean mayBeSelectedAsNextAuthMethod;
      @SuppressFBWarnings(justification = "generated code")
      private TokenListPersister tokenListPersister;
      @SuppressFBWarnings(justification = "generated code")
      private Integer validityDays;
      @SuppressFBWarnings(justification = "generated code")
      private MatrixCardGeneratorConfig matrixCardGenerator;

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

      @SuppressFBWarnings(justification = "generated code")
      public MatrixTokenController.MatrixTokenControllerBuilder identifier(String identifier) {
         this.identifier = identifier;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixTokenController.MatrixTokenControllerBuilder autoOrder(boolean autoOrder) {
         this.autoOrder = autoOrder;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixTokenController.MatrixTokenControllerBuilder autoOrderForNewUsers(boolean autoOrderForNewUsers) {
         this.autoOrderForNewUsers = autoOrderForNewUsers;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixTokenController.MatrixTokenControllerBuilder mayBeSelectedAsAuthMethod(boolean mayBeSelectedAsAuthMethod) {
         this.mayBeSelectedAsAuthMethod = mayBeSelectedAsAuthMethod;
         return this;
      }

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

      @SuppressFBWarnings(justification = "generated code")
      public MatrixTokenController.MatrixTokenControllerBuilder tokenListPersister(TokenListPersister tokenListPersister) {
         this.tokenListPersister = tokenListPersister;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixTokenController.MatrixTokenControllerBuilder validityDays(Integer validityDays) {
         this.validityDays = validityDays;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixTokenController.MatrixTokenControllerBuilder matrixCardGenerator(MatrixCardGeneratorConfig matrixCardGenerator) {
         this.matrixCardGenerator = matrixCardGenerator;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixTokenController build() {
         return new MatrixTokenController(
            this.identifier,
            this.autoOrder,
            this.autoOrderForNewUsers,
            this.mayBeSelectedAsAuthMethod,
            this.mayBeSelectedAsNextAuthMethod,
            this.tokenListPersister,
            this.validityDays,
            this.matrixCardGenerator
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "MatrixTokenController.MatrixTokenControllerBuilder(identifier="
            + this.identifier
            + ", autoOrder="
            + this.autoOrder
            + ", autoOrderForNewUsers="
            + this.autoOrderForNewUsers
            + ", mayBeSelectedAsAuthMethod="
            + this.mayBeSelectedAsAuthMethod
            + ", mayBeSelectedAsNextAuthMethod="
            + this.mayBeSelectedAsNextAuthMethod
            + ", tokenListPersister="
            + this.tokenListPersister
            + ", validityDays="
            + this.validityDays
            + ", matrixCardGenerator="
            + this.matrixCardGenerator
            + ")";
      }
   }
}
