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

import com.airlock.iam.common.api.application.configuration.validation.DateValidatorConfig;
import com.airlock.iam.core.application.configuration.contextdata.DateContextDataItemNameConfig;
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.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Plugin(description = "User context data item that stores a date (only date, no time nor time zone).", displayName = "Date User Context Data Item")
public final class DateContextDataItemDefinitionConfig implements ContextDataItemDefinitionConfig<LocalDate> {
   @PluginProperty(description = "The context data item in the context data.", optional = false)
   private DateContextDataItemNameConfig 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<DateValidatorConfig> 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,
      suggestedValues = "bday"
   )
   private String inputPurpose;

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

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

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

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

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

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

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

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

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

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

      @SuppressFBWarnings(justification = "generated code")
      public DateContextDataItemDefinitionConfig.DateContextDataItemDefinitionConfigBuilder contextDataName(DateContextDataItemNameConfig contextDataName) {
         this.contextDataName = contextDataName;
         return this;
      }

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

      @SuppressFBWarnings(justification = "generated code")
      public DateContextDataItemDefinitionConfig.DateContextDataItemDefinitionConfigBuilder validator(DateValidatorConfig validator) {
         if (this.validators == null) {
            this.validators = new ArrayList<>();
         }

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

      @SuppressFBWarnings(justification = "generated code")
      public DateContextDataItemDefinitionConfig.DateContextDataItemDefinitionConfigBuilder validators(Collection<? extends DateValidatorConfig> 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 DateContextDataItemDefinitionConfig.DateContextDataItemDefinitionConfigBuilder clearValidators() {
         if (this.validators != null) {
            this.validators.clear();
         }

         return this;
      }

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

      @SuppressFBWarnings(justification = "generated code")
      public DateContextDataItemDefinitionConfig build() {
         return new DateContextDataItemDefinitionConfig(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 "DateContextDataItemDefinitionConfig.DateContextDataItemDefinitionConfigBuilder(contextDataName="
            + this.contextDataName
            + ", required="
            + this.required
            + ", validators="
            + this.validators
            + ", inputPurpose="
            + this.inputPurpose
            + ")";
      }
   }
}
