package com.airlock.iam.flow.shared.application.configuration.item;

import com.airlock.iam.common.api.application.configuration.validation.DateAndTimeValidatorConfig;
import com.airlock.iam.core.application.configuration.contextdata.DateAndTimeContextDataItemNameConfig;
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.PluginListProperty;
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.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Plugin(
   description = "User context data item that stores a date and time value without time zone information.",
   displayName = "Date And Time User Context Data Item"
)
public final class DateAndTimeContextDataItemDefinitionConfig implements ContextDataItemDefinitionConfig<Date> {
   public static final String DATE_AND_TIME_CONTEXT_DATA_ITEM_DEFINITION_DISPLAY_NAME = "Date And Time User Context Data Item";
   @PluginProperty(description = "The context data item in the context data.", optional = false)
   private DateAndTimeContextDataItemNameConfig contextDataName;
   @BooleanProperty(
      description = "Specifies whether this context data item is required for the step to validate successfully.",
      defaultValue = "true",
      optional = true
   )
   private boolean required;
   @PluginListProperty(description = "The validators for this context data item.", optional = true)
   private List<DateAndTimeValidatorConfig> validators;
   @StringProperty(
      description = "<p>The input purpose allows labeling data items using standardized values\n(see <a href=\"https://www.w3.org/TR/WCAG22/#input-purposes\" target=\"_blank\">https://www.w3.org/TR/WCAG22/#input-purposes</a>).</p>\n<p>It is rendered using the HTML attribute \"autocomplete\".\nBrowsers can use this to automatically fill input fields with data that was previously entered in other fields with the same purpose.</p><p>Note that the input purpose provided here will be used in the default Loginapp UI components and is available to\ncustom single-page applications via the REST endpoints <code>*/info/retrieve</code>.</p>\n<p>If the Loginapp UI is used with <em>configuration-based</em> 'Customized Step UIs', the input purpose has to be defined on the UI elements\n('Input UI Element', 'Drop-Down UI Element', 'Date UI Element').</p>",
      optional = true
   )
   private String inputPurpose;

   @Override
   public String getContextDataItemName() {
      return this.contextDataName.getContextDataName();
   }

   @Override
   public Class<Date> getType() {
      return Date.class;
   }

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

   public List<DateAndTimeValidatorConfig> getValidators() {
      return this.validators;
   }

   @Override
   public Optional<String> getInputPurpose() {
      return Optional.ofNullable(this.inputPurpose);
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public DateAndTimeContextDataItemDefinitionConfig(
      DateAndTimeContextDataItemNameConfig contextDataName, boolean required, List<DateAndTimeValidatorConfig> validators, String inputPurpose
   ) {
      this.contextDataName = contextDataName;
      this.required = required;
      this.validators = validators;
      this.inputPurpose = inputPurpose;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class DateAndTimeContextDataItemDefinitionConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private DateAndTimeContextDataItemNameConfig contextDataName;
      @SuppressFBWarnings(justification = "generated code")
      private boolean required;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<DateAndTimeValidatorConfig> validators;
      @SuppressFBWarnings(justification = "generated code")
      private String inputPurpose;

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

      @SuppressFBWarnings(justification = "generated code")
      public DateAndTimeContextDataItemDefinitionConfig.DateAndTimeContextDataItemDefinitionConfigBuilder contextDataName(
         DateAndTimeContextDataItemNameConfig contextDataName
      ) {
         this.contextDataName = contextDataName;
         return this;
      }

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

      @SuppressFBWarnings(justification = "generated code")
      public DateAndTimeContextDataItemDefinitionConfig.DateAndTimeContextDataItemDefinitionConfigBuilder validator(DateAndTimeValidatorConfig validator) {
         if (this.validators == null) {
            this.validators = new ArrayList<>();
         }

         this.validators.add(validator);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DateAndTimeContextDataItemDefinitionConfig.DateAndTimeContextDataItemDefinitionConfigBuilder validators(
         Collection<? extends DateAndTimeValidatorConfig> validators
      ) {
         if (validators == null) {
            throw new NullPointerException("validators cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public DateAndTimeContextDataItemDefinitionConfig.DateAndTimeContextDataItemDefinitionConfigBuilder clearValidators() {
         if (this.validators != null) {
            this.validators.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DateAndTimeContextDataItemDefinitionConfig.DateAndTimeContextDataItemDefinitionConfigBuilder inputPurpose(String inputPurpose) {
         this.inputPurpose = inputPurpose;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DateAndTimeContextDataItemDefinitionConfig build() {
         return new DateAndTimeContextDataItemDefinitionConfig(
            this.contextDataName, this.required, switch (this.validators == null ? 0 : this.validators.size()) {
               case 0 -> Collections.emptyList();
               case 1 -> Collections.singletonList(this.validators.get(0));
               default -> Collections.unmodifiableList(new ArrayList<>(this.validators));
            }, this.inputPurpose
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "DateAndTimeContextDataItemDefinitionConfig.DateAndTimeContextDataItemDefinitionConfigBuilder(contextDataName="
            + this.contextDataName
            + ", required="
            + this.required
            + ", validators="
            + this.validators
            + ", inputPurpose="
            + this.inputPurpose
            + ")";
      }
   }
}
