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

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.impl.tokenverifier.oathotp.OathOtpSettings;
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.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.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 java.util.List;

@Plugin(
   description = "Manages OATH OTP (software OTP generators on mobile devices) tokens according to OATH standards based on H-MAC.<p>Time-based OTP (\"TOTP\" according to draft standard http://www.ietf.org/id/draft-mraihi-totp-timebased-06.txt) and counter-based OTP (\"HOTP\" according to RFC 4226) are supported.<br/>There are number of freely available clients (\"apps\") for various mobile phone operating systems. The plugin has been tested with the \"Google Authenticator\" app.</p>",
   displayName = "OATH OTP Token Controller"
)
@Groups(groupSequence = {"Basic Settings", "Advanced Settings"}, openGroups = "Basic Settings")
@PluginLicenseRestriction(moduleAffiliation = {"MobileOTP", "OathOtp"})
public class OathOtpTokenController implements TokenController {
   public static final String ID = "OATH_OTP";
   static final String MOBILE_OTP = "MobileOTP";
   @PluginProperty(
      description = "The OATH OTP settings.",
      optional = false,
      displayName = "OATH OTP Settings",
      globalPluginReference = "globalOathOtpSettings"
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   @PluginPropertyLicenseRestriction(moduleAffiliation = "OathOtp")
   private OathOtpSettings oathOtpSettings;
   @BooleanProperty(
      description = "Set this flag to true to automatically order an activation letter once this token is added to a user.",
      optional = true,
      defaultValue = "false",
      displayName = "Auto Order Activation Letter"
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private boolean autoOrderCredential;
   @BooleanProperty(
      description = "Set this flag to true to automatically order the credential if the user is created.",
      optional = true,
      defaultValue = "false"
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private boolean autoOrderForNewUsers;
   @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 token controllers.</p><p>The identifier is also used as key to translate the display name of this token controller. The key is assembled as follows: <code>edituserpage.cred.XYZ.title</code> (where XYZ is the identifier).</p>",
      optional = true,
      defaultValue = "OATH_OTP",
      suggestedValues = "OATH_OTP"
   )
   @GroupProperty(groupIdentifier = "Advanced Settings")
   @PluginPropertyLicenseRestriction(moduleAffiliation = "OathOtp")
   private String identifier;
   @StringListProperty(
      description = "Defines a list of context data properties that are considered to part of the credential data. The specified context data properties are deleted (set to \"null\") when the credential is deleted (in addition to the credential data field, the serial number, the letter attribute and the order flag). <br/>Make sure, the underlying persister plugin is configured to persist the specified context data properties.",
      optional = true,
      minElements = 1,
      exampleElements = {"cert_tbs", "tok_additional_data"}
   )
   @GroupProperty(groupIdentifier = "Advanced Settings")
   @PluginPropertyLicenseRestriction(moduleAffiliation = "OathOtp")
   private List<String> deletePropertiesWithCredential;

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

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

   public OathOtpSettings getOathOtpSettings() {
      return this.oathOtpSettings;
   }

   public boolean isAutoOrderCredential() {
      return this.autoOrderCredential;
   }

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

   public List<String> getDeletePropertiesWithCredential() {
      return this.deletePropertiesWithCredential;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public OathOtpTokenController(
      OathOtpSettings oathOtpSettings,
      boolean autoOrderCredential,
      boolean autoOrderForNewUsers,
      String identifier,
      List<String> deletePropertiesWithCredential
   ) {
      this.oathOtpSettings = oathOtpSettings;
      this.autoOrderCredential = autoOrderCredential;
      this.autoOrderForNewUsers = autoOrderForNewUsers;
      this.identifier = identifier;
      this.deletePropertiesWithCredential = deletePropertiesWithCredential;
   }

   @SuppressFBWarnings(justification = "generated code")
   public void setAutoOrderForNewUsers(boolean autoOrderForNewUsers) {
      this.autoOrderForNewUsers = autoOrderForNewUsers;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class OathOtpTokenControllerBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private OathOtpSettings oathOtpSettings;
      @SuppressFBWarnings(justification = "generated code")
      private boolean autoOrderCredential;
      @SuppressFBWarnings(justification = "generated code")
      private boolean autoOrderForNewUsers;
      @SuppressFBWarnings(justification = "generated code")
      private String identifier;
      @SuppressFBWarnings(justification = "generated code")
      private List<String> deletePropertiesWithCredential;

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

      @SuppressFBWarnings(justification = "generated code")
      public OathOtpTokenController.OathOtpTokenControllerBuilder oathOtpSettings(OathOtpSettings oathOtpSettings) {
         this.oathOtpSettings = oathOtpSettings;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OathOtpTokenController.OathOtpTokenControllerBuilder autoOrderCredential(boolean autoOrderCredential) {
         this.autoOrderCredential = autoOrderCredential;
         return this;
      }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public OathOtpTokenController.OathOtpTokenControllerBuilder deletePropertiesWithCredential(List<String> deletePropertiesWithCredential) {
         this.deletePropertiesWithCredential = deletePropertiesWithCredential;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OathOtpTokenController build() {
         return new OathOtpTokenController(
            this.oathOtpSettings, this.autoOrderCredential, this.autoOrderForNewUsers, this.identifier, this.deletePropertiesWithCredential
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "OathOtpTokenController.OathOtpTokenControllerBuilder(oathOtpSettings="
            + this.oathOtpSettings
            + ", autoOrderCredential="
            + this.autoOrderCredential
            + ", autoOrderForNewUsers="
            + this.autoOrderForNewUsers
            + ", identifier="
            + this.identifier
            + ", deletePropertiesWithCredential="
            + this.deletePropertiesWithCredential
            + ")";
      }
   }
}
