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

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

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.ivu.elect.business.anschrift.entity.Anschrift;
import de.ivu.elect.business.ergebnis.entity.Gewaehlt;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.kandidatur.boundary.ErsatzkandidaturPruefer;
import de.ivu.elect.business.kandidatur.boundary.ErsatzkandidaturPruefer.Result;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.kandidatur.entity.ListenkandidaturAnzahlNennungenProperty;
import de.ivu.elect.business.kandidatur.entity.ListenkandidaturArt;
import de.ivu.elect.business.kandidatur.entity.ListenkandidaturMeta;
import de.ivu.elect.business.kandidatur.entity.ListenkandidaturProperties;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.presentation.dynamicform.AbstractEnumProperty;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.Property;
import de.ivu.elect.presentation.personenregister.form.AbstractPersonenregisterPropertiesViewFormBuilder;

public class ListenkandidaturViewFormBuilder extends AbstractPersonenregisterPropertiesViewFormBuilder {

  private static final long serialVersionUID = 1L;

  @Inject
  protected transient ListenkandidaturMeta listenkandidaturMeta;

  @Inject
  protected transient ErsatzkandidaturPruefer ersatzkandidaturPruefer;

  @Inject
  protected transient KandidaturViewFormBuilder kandidaturViewFormBuilder;

  public ListenkandidaturViewFormBuilder() {
    super();
  }

  public String getEntityEinzahlMessage(@Nullable Gebiet gebiet) {
    return listenkandidaturMeta.getEinzahlMessage();
  }

  public void addListenkandidaturProperties(FormBuilder formBuilder, Listenkandidatur listenkandidatur, boolean readonly) {
    boolean propertiesErweitertInitialVisibleOnPageLoad = kandidaturViewFormBuilder.isKandidaturPropertiesErweitertInitialVisibleOnPageLoad(listenkandidatur);

    Wahl wahl = listenkandidatur.getWahl();

    ListenkandidaturProperties listenkandidaturProperties = listenkandidatur.getProperties();

    addListenkandidaturArtProperty(formBuilder, listenkandidatur, propertiesErweitertInitialVisibleOnPageLoad, readonly);

    formBuilder.addProperty(listenkandidaturProperties.getEingereichtePositionProperty()) //
        .withVisibleOnPageLoad(propertiesErweitertInitialVisibleOnPageLoad) //
        .withReadonly(readonly);

    if (listenkandidatur.isPersistent()) {
      formBuilder.addProperty(listenkandidaturProperties.getVorgegebenePositionProperty()).withReadonly(readonly);
    }

    if (wahl != null && wahl.isWahlMitMehrfachnennungen()) {
      formBuilder.addProperty(new ListenkandidaturAnzahlNennungenProperty(listenkandidatur)) //
          .withVisibleOnPageLoad(propertiesErweitertInitialVisibleOnPageLoad) //
          .withReadonly(readonly);
    }
  }

  protected void addListenkandidaturArtProperty(FormBuilder formBuilder, Listenkandidatur listenkandidatur, boolean propertiesErweitertInitialVisibleOnPageLoad, boolean readonly) {
    Wahl wahl = listenkandidatur.getWahl();

    Result listenkandidaturMarkiertAlsErsatzkandidaturHinzufuegenResult = ersatzkandidaturPruefer.checkListenkandidaturMarkiertAlsErsatzkandidaturHinzufuegen(wahl, listenkandidatur);

    boolean listenkandidaturArtErsatzkandidaturSelectable = listenkandidatur.isListenkandidaturMarkiertAlsErsatzkandidatur()
        || listenkandidaturMarkiertAlsErsatzkandidaturHinzufuegenResult.isWeitereErsatzkandidaturZulaessig();

    AbstractEnumProperty<ListenkandidaturArt> listenkandidaturArtProperty = listenkandidatur.getProperties().getListenkandidaturArtProperty();
    List<ListenkandidaturArt> listenkandidaturArtenZulaessig = new ArrayList<>(listenkandidaturArtProperty.getValues());

    if (!listenkandidaturArtErsatzkandidaturSelectable) {
      listenkandidaturArtenZulaessig.removeIf(ListenkandidaturArt::isErsatzkandidatur); // ELECT-8925
    }

    if (wahl != null && wahl.isWahlMitErsatzkandidaturen() || listenkandidaturArtenZulaessig.size() > 1L) {
      formBuilder.addProperty(listenkandidaturArtProperty) //
          .setValues(listenkandidaturArtenZulaessig) //
          .withReadonly(readonly || listenkandidaturArtenZulaessig.size() == 1) //
          .withVisibleOnPageLoad(listenkandidaturArtenZulaessig.size() > 1 || propertiesErweitertInitialVisibleOnPageLoad);

      if (!listenkandidaturArtErsatzkandidaturSelectable) {
        long anzahlErsatzkandidaturenMaximal = listenkandidaturMarkiertAlsErsatzkandidaturHinzufuegenResult.getAnzahlErsatzkandidaturenMaximal();

        if (anzahlErsatzkandidaturenMaximal > 0L) { // ELECT-15748
          formBuilder.withTooltip(
              getMessage("listenkandidatur.edit.listenkandidatur.art.ERSATZKANDIDATUR.max.anzahl.tooltip", getMessage(ListenkandidaturArt.ERSATZKANDIDATUR), anzahlErsatzkandidaturenMaximal));
        }
      }
    }
  }

  public void addKandidaturProperties(FormBuilder formBuilder, Listenkandidatur listenkandidatur, boolean readonly) {
    kandidaturViewFormBuilder.addKandidaturProperties(formBuilder, listenkandidatur, readonly, isPraesentationPropertiesReadonly(), readonly);

    setListenkandidaturKandidaturPropertiesRequired(formBuilder, listenkandidatur);
  }

  protected boolean isPraesentationPropertiesReadonly() {
    return false;
  }

  protected FormBuilder setListenkandidaturKandidaturPropertiesRequired(FormBuilder formBuilder, Listenkandidatur listenkandidatur) {
    setListenkandidaturPersonendatenPropertiesRequired(formBuilder, listenkandidatur);
    setListenkandidaturAnschriftPropertiesRequired(formBuilder, listenkandidatur, listenkandidatur.getAnschrift());

    return formBuilder;
  }

  public FormBuilder setListenkandidaturPersonendatenPropertiesRequired(FormBuilder formBuilder, Listenkandidatur listenkandidatur) {
    return setPropertiesRequired(formBuilder, getListenkandidaturPersonendatenPropertiesRequired(listenkandidatur));
  }

  public Set<Class< ? extends Property>> getListenkandidaturPersonendatenPropertiesRequired(Listenkandidatur listenkandidatur) {
    return kandidaturViewFormBuilder.getKandidaturPersonendatenPropertiesRequired(listenkandidatur);
  }

  public FormBuilder setListenkandidaturAnschriftPropertiesRequired(FormBuilder formBuilder, Listenkandidatur listenkandidatur, Anschrift anschrift) {
    return setPropertiesRequired(formBuilder, getListenkandidaturAnschriftPropertiesRequired(listenkandidatur, anschrift));
  }

  public Set<Class< ? extends Property>> getListenkandidaturAnschriftPropertiesRequired(Listenkandidatur listenkandidatur, Anschrift anschrift) {
    return kandidaturViewFormBuilder.getKandidaturAnschriftPropertiesRequired(listenkandidatur, anschrift);
  }

  public void addGewaehltVorperiodeProperties(FormBuilder formBuilder, Kandidatur kandidatur, Gewaehlt gewaehlt, boolean readonly) {
    kandidaturViewFormBuilder.addGewaehltVorperiodeProperties(formBuilder, kandidatur, gewaehlt, readonly);
  }

  public Gewaehlt createGewaehltVorperiode(Wahl wahl) {
    return kandidaturViewFormBuilder.createGewaehltVorperiode(wahl);
  }

  @Override
  public Collection<Class< ? extends Property>> getPersonenregisterPropertiesUebernommen(Personendaten personendaten) {
    return kandidaturViewFormBuilder.getPersonenregisterPropertiesUebernommen(personendaten);
  }

  public void preSaveEntity(Listenkandidatur listenkandidatur) {
    kandidaturViewFormBuilder.preSaveEntity(listenkandidatur);
  }
}
