
package de.ivu.elect.jee.presentation.dynamicform;

import java.util.Collection;

import javax.faces.convert.Converter;
import javax.faces.convert.NumberConverter;
import javax.faces.validator.LongRangeValidator;
import javax.faces.validator.Validator;

public abstract class AbstractNumberProperty<T extends Number> extends AbstractProperty implements PropertyHavingMinAndMaxLength {

  private Integer minLength;

  private Integer maxLength;

  protected AbstractNumberProperty() {
    super();
  }

  @Override
  protected boolean mustBeAccessableOnPageLoadByValue() {
    if (super.mustBeAccessableOnPageLoadByValue()) {
      return true;
    }

    return notAllEqual(getDefaultValue(), getValue());
  }

  @Override
  public Converter getDefaultConverter() {
    NumberConverter numberConverter = new NumberConverter();
    numberConverter.setLocale(getLocale());
    numberConverter.setGroupingUsed(true);

    return numberConverter;
  }

  @Override
  public PropertyType getDefaultType() {
    return PropertyType.INPUT_NUMBER;
  }

  @Override
  protected boolean hasDefaultValue() {
    return notNullOrBlank(getDefaultValue());
  }

  public T getDefaultValue() {
    return null;
  }

  @Override
  public boolean hasValue() {
    return notNullOrBlank(getValue());
  }

  public abstract T getValue();

  public abstract void setValue(T value);

  public abstract long getMinValue();

  public abstract long getMaxValue();

  public int getDefaultMinLength() {
    return 0;
  }

  @Override
  public int getMinLength() {
    if (minLength == null) {
      return getDefaultMinLength();
    }

    return minLength;
  }

  @Override
  public void setMinLength(int minLength) {
    this.minLength = minLength;
  }

  public int getDefaultMaxLength() {
    /*
     * ELECT-13767, mehr oder weniger willkürlich gewählt, weil eigentlich auch egal, da Konvertierbarkeit sowie Min- und Max-WERTE IMMER EXTRA VALIDIERT werden und die Länge der "Darstellung" (mit
     * oder ohne Vorzeichen, Trennzeichen, etc.) deshalb nicht beschränkt werden muss...
     *
     * ... bspw. Integer#MIN_VALUE -> "-2.147.483.648".length() == 14, Long#MIN_VALUE -> "-9.223.372.036.854.775.808".length() == 26...
     */
    return 32;
  }

  @Override
  public int getMaxLength() {
    if (maxLength == null) {
      return getDefaultMaxLength();
    }

    return maxLength;
  }

  @Override
  public void setMaxLength(int maxLength) {
    this.maxLength = maxLength;
  }

  @Override
  public Collection<Validator> getValidators() {
    Collection<Validator> result = super.getValidators();
    result.add(new LongRangeValidator(getMaxValue(), getMinValue()));

    return result;
  }
}
