
package de.ivu.elect.business.entschaedigung.boundary;

import static java.util.Arrays.asList;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import de.ivu.elect.business.entschaedigung.control.EntschaedigungsartDefaultComparator;
import de.ivu.elect.business.entschaedigung.entity.EntschaedigungConstants;
import de.ivu.elect.business.entschaedigung.entity.Entschaedigungsart;
import de.ivu.elect.business.person.boundary.KontoverbindungFilterKriterium;
import de.ivu.elect.business.person.boundary.SearchParametersMitPersonendatenNamen;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.person.entity.PersonendatenProperties;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.jee.entity.customdata.EmptyCustomData;
import de.ivu.elect.jee.presentation.dynamicform.AbstractEnumProperty;
import de.ivu.elect.jee.presentation.dynamicform.Property;
import de.ivu.elect.jee.presentation.dynamicform.PropertyType;
import de.ivu.elect.presentation.LambdaEntitySelectManyProperty;
import de.ivu.elect.presentation.person.form.KontoverbindungFilterKriteriumProperty;

public class EntschaedigungToCalculateParameters extends AbstractEntschaedigungSearchParameters implements SearchParametersMitPersonendatenNamen {

  private static final long serialVersionUID = 1L;

  private Wahl wahl;

  private Wahltermin wahltermin;

  private Collection<Entschaedigungsart> entschaedigungsarten;

  private Personendaten personendaten;

  private KontoverbindungFilterKriterium kontoverbindungFilterKriterium;

  private EntschaedigungKriteriumEinsatzStatus entschaedigungKriteriumEinsatzStatus;

  private EntschaedigungKriteriumGesamtbetrag entschaedigungKriteriumGesamtbetrag;

  /**
   * Diese Klasse nicht per @Inject verwenden, sondern zur Verwendung per @Inject ableiten, cf. EntschaedigungInAuszahlungBulkCreateParameters, oder zur Berechnung per parametrisierten Konstruktur
   * instanziieren!!!
   */
  protected EntschaedigungToCalculateParameters() {
    this(null, null, new ArrayList<>());
  }

  public EntschaedigungToCalculateParameters(Wahl wahl, Wahltermin wahltermin, Collection<Entschaedigungsart> entschaedigungsarten) {
    super();

    this.wahl = wahl;
    this.wahltermin = wahltermin;

    this.entschaedigungsarten = entschaedigungsarten;

    this.personendaten = null;

    this.kontoverbindungFilterKriterium = KontoverbindungFilterKriterium.ALLE;

    this.entschaedigungKriteriumEinsatzStatus = EntschaedigungKriteriumEinsatzStatus.AUSZAHLBAR;
    this.entschaedigungKriteriumGesamtbetrag = EntschaedigungKriteriumGesamtbetrag.NUR_GROESSER_NULL;
  }

  public boolean hasWahl() {
    return getWahl() != null;
  }

  public Wahl getWahl() {
    return wahl;
  }

  public void setWahl(Wahl wahl) {
    this.wahl = wahl;
  }

  public boolean hasWahltermin() {
    return getWahltermin() != null;
  }

  public Wahltermin getWahltermin() {
    return wahltermin;
  }

  public void setWahltermin(Wahltermin wahltermin) {
    this.wahltermin = wahltermin;
  }

  public boolean hasEntschaedigungsarten() {
    return getEntschaedigungsarten() != null && !getEntschaedigungsarten().isEmpty();
  }

  public Collection<Entschaedigungsart> getEntschaedigungsarten() {
    return entschaedigungsarten;
  }

  public void setEntschaedigungsarten(Collection<Entschaedigungsart> entschaedigungsarten) {
    this.entschaedigungsarten = entschaedigungsarten;
  }

  public Property getEntschaedigungsartenProperty(List<Entschaedigungsart> values) {
    values.sort(new EntschaedigungsartDefaultComparator());

    return new LambdaEntitySelectManyProperty<>(values, PropertyType.SELECT_MANY_CHECKBOX_MENU, this::setEntschaedigungsarten, this::getEntschaedigungsarten, Entschaedigungsart::getBezeichnung,
        EntschaedigungConstants.MESSAGE_KEY_ENTSCHAEDIGUNGSART_ID_MEHRZAHL, true);
  }

  @Override
  public String getFamilienname() {
    return getPersonendaten().getFamilienname();
  }

  @Override
  public void setFamilienname(String familienname) {
    getPersonendaten().setFamilienname(familienname);
  }

  @Override
  public Property getFamiliennameProperty() {
    Property property = getPersonendatenProperties().getFamiliennameProperty();
    property.setRequired(false);

    return property;
  }

  @Override
  public String getVorname() {
    return getPersonendaten().getRufname();
  }

  @Override
  public void setVorname(String vorname) {
    getPersonendaten().setRufname(vorname);
  }

  @Override
  public Property getVornameProperty() {
    Property property = getPersonendatenProperties().getRufnameProperty();
    property.setRequired(false);
    property.setLabel(getMessage(SearchParametersMitPersonendatenNamen.MESSAGE_KEY_VORNAME_EINZAHL));

    return property;
  }

  private PersonendatenProperties getPersonendatenProperties() {
    return getPersonendaten().getProperties();
  }

  private Personendaten getPersonendaten() {
    if (personendaten == null) {
      personendaten = new Personendaten(EmptyCustomData.INSTANCE);
    }

    return personendaten;
  }

  public boolean hasEntschaedigungKriteriumEinsatzStatus() {
    return getEntschaedigungKriteriumEinsatzStatus() != null;
  }

  public EntschaedigungKriteriumEinsatzStatus getEntschaedigungKriteriumEinsatzStatus() {
    return entschaedigungKriteriumEinsatzStatus;
  }

  public void setEntschaedigungKriteriumEinsatzStatus(EntschaedigungKriteriumEinsatzStatus entschaedigungKriteriumEinsatzStatus) {
    this.entschaedigungKriteriumEinsatzStatus = entschaedigungKriteriumEinsatzStatus;
  }

  public EntschaedigungKriteriumEinsatzStatusProperty getEntschaedigungKriteriumEinsatzStatusProperty() {
    return new EntschaedigungKriteriumEinsatzStatusProperty(this);
  }

  public boolean hasKontoverbindungFilterKriterium() {
    return getKontoverbindungFilterKriterium() != null && !KontoverbindungFilterKriterium.ALLE.equals(getKontoverbindungFilterKriterium());
  }

  public KontoverbindungFilterKriterium getKontoverbindungFilterKriterium() {
    // NOTE, dass KontoverbindungFilterKriteriumProperty#defaultRequired == false gilt!
    if (kontoverbindungFilterKriterium == null) {
      kontoverbindungFilterKriterium = KontoverbindungFilterKriterium.ALLE;
    }

    return kontoverbindungFilterKriterium;
  }

  public void setKontoverbindungFilterKriterium(KontoverbindungFilterKriterium kontoverbindungFilterKriterium) {
    this.kontoverbindungFilterKriterium = kontoverbindungFilterKriterium;
  }

  public KontoverbindungFilterKriteriumProperty getPersonendatenKontoverbindungFilterKriteriumProperty() {
    return new KontoverbindungFilterKriteriumProperty(this::getKontoverbindungFilterKriterium, this::setKontoverbindungFilterKriterium);
  }

  public boolean hasEntschaedigungKriteriumGesamtbetrag() {
    return getEntschaedigungKriteriumGesamtbetrag() != null;
  }

  public EntschaedigungKriteriumGesamtbetrag getEntschaedigungKriteriumGesamtbetrag() {
    if (entschaedigungKriteriumGesamtbetrag == null) {
      entschaedigungKriteriumGesamtbetrag = EntschaedigungKriteriumGesamtbetrag.NUR_GROESSER_NULL;
    }

    return entschaedigungKriteriumGesamtbetrag;
  }

  public void setEntschaedigungKriteriumGesamtbetrag(EntschaedigungKriteriumGesamtbetrag entschaedigungKriteriumGesamtbetrag) {
    this.entschaedigungKriteriumGesamtbetrag = entschaedigungKriteriumGesamtbetrag;
  }

  public EntschaedigungKriteriumGesamtbetragProperty getEntschaedigungKriteriumGesamtbetragProperty() {
    return new EntschaedigungKriteriumGesamtbetragProperty(this);
  }

  @Override
  public void reset() {
    wahl = null;
    wahltermin = null;

    entschaedigungsarten = new ArrayList<>();

    personendaten = null;

    kontoverbindungFilterKriterium = KontoverbindungFilterKriterium.ALLE;

    entschaedigungKriteriumEinsatzStatus = EntschaedigungKriteriumEinsatzStatus.AUSZAHLBAR;
    entschaedigungKriteriumGesamtbetrag = EntschaedigungKriteriumGesamtbetrag.NUR_GROESSER_NULL;

    super.reset();
  }

  public static class EntschaedigungKriteriumEinsatzStatusProperty extends AbstractEnumProperty<EntschaedigungKriteriumEinsatzStatus> {

    private final EntschaedigungToCalculateParameters entschaedigungToCalculateParameters;

    public EntschaedigungKriteriumEinsatzStatusProperty(EntschaedigungToCalculateParameters entschaedigungToCalculateParameters) {
      super();

      this.entschaedigungToCalculateParameters = entschaedigungToCalculateParameters;
    }

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

    @Override
    public EntschaedigungKriteriumEinsatzStatus getValue() {
      return entschaedigungToCalculateParameters.getEntschaedigungKriteriumEinsatzStatus();
    }

    @Override
    public void setValue(EntschaedigungKriteriumEinsatzStatus value) {
      entschaedigungToCalculateParameters.setEntschaedigungKriteriumEinsatzStatus(value);
    }

    @Override
    public List<EntschaedigungKriteriumEinsatzStatus> getValues() {
      return asList(EntschaedigungKriteriumEinsatzStatus.values());
    }

    @Override
    protected Class<EntschaedigungKriteriumEinsatzStatus> getEnumClass() {
      return EntschaedigungKriteriumEinsatzStatus.class;
    }

    @Override
    public String getDefaultLabel() {
      return getMessage("EntschaedigungKriteriumEinsatzStatus.label");
    }
  }

  public static class EntschaedigungKriteriumGesamtbetragProperty extends AbstractEnumProperty<EntschaedigungKriteriumGesamtbetrag> {

    private final EntschaedigungToCalculateParameters entschaedigungToCalculateParameters;

    public EntschaedigungKriteriumGesamtbetragProperty(EntschaedigungToCalculateParameters entschaedigungToCalculateParameters) {
      super();

      this.entschaedigungToCalculateParameters = entschaedigungToCalculateParameters;
    }

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

    @Override
    public EntschaedigungKriteriumGesamtbetrag getValue() {
      return entschaedigungToCalculateParameters.getEntschaedigungKriteriumGesamtbetrag();
    }

    @Override
    public void setValue(EntschaedigungKriteriumGesamtbetrag value) {
      entschaedigungToCalculateParameters.setEntschaedigungKriteriumGesamtbetrag(value);
    }

    @Override
    public List<EntschaedigungKriteriumGesamtbetrag> getValues() {
      return asList(EntschaedigungKriteriumGesamtbetrag.values());
    }

    @Override
    protected Class<EntschaedigungKriteriumGesamtbetrag> getEnumClass() {
      return EntschaedigungKriteriumGesamtbetrag.class;
    }

    @Override
    public String getDefaultLabel() {
      return getMessage("EntschaedigungKriteriumGesamtbetrag.label");
    }
  }
}
