
package de.ivu.elect.presentation.konfiguration.form;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.annotation.Nullable;
import javax.enterprise.context.RequestScoped;

import de.ivu.elect.business.konfiguration.entity.CustomParameter;
import de.ivu.elect.jee.presentation.dynamicform.AbstractBooleanProperty;
import de.ivu.elect.jee.presentation.dynamicform.AbstractDateProperty;
import de.ivu.elect.jee.presentation.dynamicform.AbstractRedisplayPasswordProperty;
import de.ivu.elect.jee.presentation.dynamicform.AbstractStringProperty;
import de.ivu.elect.jee.presentation.dynamicform.AbstractTimestampProperty;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.Property;
import de.ivu.elect.jee.presentation.dynamicform.PropertyType;
import de.ivu.elect.jee.presentation.dynamicform.ReadOnlyStringProperty;
import de.ivu.elect.presentation.ViewFormBuilder;


import static org.apache.commons.lang3.StringUtils.isNotBlank;

@RequestScoped
public class CustomParameterViewFormBuilder extends ViewFormBuilder {

  private static final long serialVersionUID = 1L;

  public CustomParameterViewFormBuilder() {
    super();
  }

  public void addProperties(FormBuilder formBuilder, CustomParameter<?> parameter, AbstractStringProperty wertStringProperty) {
    String beschreibung = parameter.getBeschreibung(getMessages());

    if (isNotBlank(beschreibung)) {
      // NOTE ELECT-5602, dass diese Position momentan erforderlich ist, damit die Validierung funktioniert!!!
      formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("custom.parameter.beschreibung"), beschreibung));
    }

    String label = parameter.getKurzname(getMessages());
    String tooltip = ""; // Beschreibung wird angezeigt!

    addProperty(formBuilder, parameter, wertStringProperty, label, tooltip);
  }

  public void addProperty(FormBuilder formBuilder, CustomParameter<?> parameter, AbstractStringProperty wertStringProperty, String label, String tooltip) {
    Property wertProperty = createWertProperty(parameter, wertStringProperty);

    formBuilder.addProperty(wertProperty).withLabel(label);

    if (isNotBlank(tooltip)) {
      formBuilder.withTooltip(tooltip);
    }

    if (parameter.expectsWertIsReadonly()) {
      formBuilder.addProperty(createHinweisReadonlyProperty());

      formBuilder.globalReadonly();
    }

    parameter.getTemplate().ifPresent(template -> template.getWertValidators().forEach(formBuilder::withValidator));
    parameter.getWertTyp().getValidators(parameter).forEach(formBuilder::withValidator);
  }

  private Property createWertProperty(CustomParameter<?> parameter, AbstractStringProperty wertStringProperty) {
    Property result = wertStringProperty;

    if (parameter.expectsWertIsStringMultiline()) {
      result.setType(PropertyType.INPUT_TEXTAREA);
      result.setStyleClass("ui-inputtextarea-large");
    } else if (parameter.expectsWertIsSecret() /* ELECTMUC-3034&& !hasUseCasePermission(editSecretsClearText)*/) {
      result = createWertSecretProperty(wertStringProperty);
    } else if (parameter.expectsWertIsBoolean()) {
      result = createWertBooleanProperty(parameter);
    } else if (parameter.expectsWertIsDate()) {
      result = createWertDateProperty(parameter);
    } else if (parameter.expectsWertIsTimestamp()) {
      result = createWertTimestampProperty(parameter);
    } else if (parameter.expectsWertIsEnum()) {
      result = new CustomParameterSelectOneMenuEnumProperty(parameter);
    } else if (parameter.expectsWertIsSelect()) {
      result = createWertSelectProperty(parameter);
    }

    return result;
  }

  private Property createWertSecretProperty(AbstractStringProperty wertStringProperty) {
    return new CustomPasswordProperty(wertStringProperty);
  }

  private Property createWertSelectProperty(CustomParameter<?> parameter) {
    return new CustomParameterSelectOneMenuStringProperty(parameter);
  }

  private Property createWertDateProperty(CustomParameter<?> parameter) {
    return new AbstractDateProperty() {

      @Override
      public boolean getDefaultRequired() {
        return false;
      }

      @Nullable
      @Override
      public Date getValue() {
        return CustomParameter.parseDate(parameter.getWert());
      }

      @Override
      public void setValue(Date date) {
        if (date == null) {
          parameter.setWert(null);
        } else {
          parameter.setWert(new SimpleDateFormat(CustomParameter.TIMESTAMP_PATTERN).format(date));
        }
      }

      @Override
      public String getDefaultLabel() {
        return "";
      }
    };

  }

  private Property createWertTimestampProperty(CustomParameter<?> parameter) {
    return new AbstractTimestampProperty() {

      @Override
      public boolean getDefaultRequired() {
        return false;
      }

      @Nullable
      @Override
      public Date getValue() {
        return CustomParameter.parseDate(parameter.getWert());
      }

      @Override
      public void setValue(Date date) {
        if (date == null) {
          parameter.setWert(null);
        } else {
          parameter.setWert(new SimpleDateFormat(CustomParameter.TIMESTAMP_PATTERN).format(date));
        }
      }

      @Override
      public String getDefaultLabel() {
        return "";
      }
    };

  }

  private Property createWertBooleanProperty(CustomParameter<?> parameter) {
    return new AbstractBooleanProperty() {

      @Override
      public boolean getDefaultRequired() {
        return false;
      }

      @Override
      public Boolean getValue() {
        return Boolean.parseBoolean(parameter.getWert());
      }

      @Override
      public String getDefaultLabel() {
        return "";
      }

      @Override
      public void setValue(Boolean value) {
        parameter.setWert(String.valueOf(Boolean.TRUE.equals(value)));
      }
    };
  }

  private ReadOnlyStringProperty createHinweisReadonlyProperty() {
    return new ReadOnlyStringProperty(getMessage("custom.parameter.readonly.label"), getMessage("custom.parameter.readonly.message"));
  }

  private static class CustomPasswordProperty extends AbstractRedisplayPasswordProperty {

    private final AbstractStringProperty wertStringProperty;

    public CustomPasswordProperty(AbstractStringProperty wertStringProperty) {
      super("", "");
      this.wertStringProperty = wertStringProperty;
    }

    @Override
    public boolean getDefaultRequired() {
      return wertStringProperty.getDefaultRequired();
    }

    @Override
    public int getDefaultMaxLength() {
      return wertStringProperty.getDefaultMaxLength();
    }

    @Override
    public boolean isFeedback() {
      return false; // Keine Passwortstärke messen
    }

    @Override
    public String getValueInternal() {
      return wertStringProperty.getValue();
    }

    @Override
    public void setValueInternal(String value) {
      wertStringProperty.setValue(value);
    }

    @Override
    public String getDefaultLabel() {
      return wertStringProperty.getDefaultLabel();
    }
  }
}
