package com.airlock.iam.admin.application.configuration.generic.ui;

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.property.BooleanProperty;
import com.airlock.iam.plugin.api.annotation.property.RegexProperty;
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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Optional;
import java.util.regex.Pattern;

@Plugin(description = "Renders an HTML input tag for a string property.", displayName = "String Input Token Controller Element")
public final class StringInputTokenControllerUiElementConfig implements TokenControllerUiElementConfig {
   @StringProperty(
      description = "Label for the field. The UI treats it as a key to translate.\nIf there is no translation, the label is shown in the UI as is.",
      exampleValues = {"userdata.label.email", "user.securid.username"},
      optional = false
   )
   private String label;
   @StringProperty(
      description = "The property to use as value for this field.\n<p>The referenced property must be available in the <code>attributes</code> value of the generic token REST call response.\nIf the property is nested, e.g. inside the <code>contextData</code> key, it can be referenced with dot notation (see example values).</p><p>The ID of the response is referenced by using the reserved value <code>@id</code>.</p>",
      optional = false,
      exampleValues = {"serialNumber", "contextData.email", "@id"}
   )
   private String property;
   @StringProperty(
      description = "Displays a placeholder when the field has no value.\nThe placeholder is not interpreted as value and disappears when typing in the field.",
      optional = true
   )
   private String placeholder;
   @BooleanProperty(
      description = "Whether this field must have a value when the token is added or updated.\nRequired fields are marked with an asterisk.",
      defaultValue = "false",
      optional = true
   )
   private boolean required;
   @BooleanProperty(
      description = "If enabled, the field is read-only and cannot be altered by administrators via the UI.",
      displayName = "Read-only",
      defaultValue = "false",
      optional = true
   )
   private boolean readOnly;
   private static final String READ_ONLY_PROPERTY = "readOnly";
   @BooleanProperty(
      description = "If enabled, this UI element is hidden if it has no value.",
      displayName = "Hide If Empty",
      defaultValue = "false",
      optional = true
   )
   private boolean hideIfEmpty;
   private static final String HIDE_IF_EMPTY_PROPERTY = "hideIfEmpty";
   @RegexProperty(
      description = "Validates the input against the defined expression.\nIf validation fails, an error on this field is shown to the administrator\nand the token cannot be added or updated.",
      optional = true
   )
   private Pattern validation;

   @ConfigurationValidator
   static void checkHideIfEmptyAllowed(PluginConfiguration pc, ConfigurationEnvironment env, ConfigurationContext context, Environment validationEnvironment) throws PropertyConfigurationException {
      TokenControllerUiElementConfig.validateHideIfEmptyAllowed(pc, env, context, "readOnly", "hideIfEmpty");
   }

   public String getLabel() {
      return this.label;
   }

   public String getProperty() {
      return this.property;
   }

   public Optional<String> getPlaceholder() {
      return Optional.ofNullable(this.placeholder);
   }

   public boolean isRequired() {
      return this.required;
   }

   public boolean isReadOnly() {
      return this.readOnly;
   }

   public boolean isHideIfEmpty() {
      return this.hideIfEmpty;
   }

   public Pattern getValidation() {
      return this.validation;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public StringInputTokenControllerUiElementConfig(
      String label, String property, String placeholder, boolean required, boolean readOnly, boolean hideIfEmpty, Pattern validation
   ) {
      this.label = label;
      this.property = property;
      this.placeholder = placeholder;
      this.required = required;
      this.readOnly = readOnly;
      this.hideIfEmpty = hideIfEmpty;
      this.validation = validation;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class StringInputTokenControllerUiElementConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String label;
      @SuppressFBWarnings(justification = "generated code")
      private String property;
      @SuppressFBWarnings(justification = "generated code")
      private String placeholder;
      @SuppressFBWarnings(justification = "generated code")
      private boolean required;
      @SuppressFBWarnings(justification = "generated code")
      private boolean readOnly;
      @SuppressFBWarnings(justification = "generated code")
      private boolean hideIfEmpty;
      @SuppressFBWarnings(justification = "generated code")
      private Pattern validation;

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

      @SuppressFBWarnings(justification = "generated code")
      public StringInputTokenControllerUiElementConfig.StringInputTokenControllerUiElementConfigBuilder label(String label) {
         this.label = label;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StringInputTokenControllerUiElementConfig.StringInputTokenControllerUiElementConfigBuilder property(String property) {
         this.property = property;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StringInputTokenControllerUiElementConfig.StringInputTokenControllerUiElementConfigBuilder placeholder(String placeholder) {
         this.placeholder = placeholder;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StringInputTokenControllerUiElementConfig.StringInputTokenControllerUiElementConfigBuilder required(boolean required) {
         this.required = required;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StringInputTokenControllerUiElementConfig.StringInputTokenControllerUiElementConfigBuilder readOnly(boolean readOnly) {
         this.readOnly = readOnly;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StringInputTokenControllerUiElementConfig.StringInputTokenControllerUiElementConfigBuilder hideIfEmpty(boolean hideIfEmpty) {
         this.hideIfEmpty = hideIfEmpty;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StringInputTokenControllerUiElementConfig.StringInputTokenControllerUiElementConfigBuilder validation(Pattern validation) {
         this.validation = validation;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StringInputTokenControllerUiElementConfig build() {
         return new StringInputTokenControllerUiElementConfig(
            this.label, this.property, this.placeholder, this.required, this.readOnly, this.hideIfEmpty, this.validation
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "StringInputTokenControllerUiElementConfig.StringInputTokenControllerUiElementConfigBuilder(label="
            + this.label
            + ", property="
            + this.property
            + ", placeholder="
            + this.placeholder
            + ", required="
            + this.required
            + ", readOnly="
            + this.readOnly
            + ", hideIfEmpty="
            + this.hideIfEmpty
            + ", validation="
            + this.validation
            + ")";
      }
   }
}
