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

import java.util.Set;
import java.util.stream.Collectors;

import javax.enterprise.inject.Specializes;
import javax.inject.Inject;

import de.ivu.elect.business.sitzberechnung.control.Sitzberechnungsalgorithmus;
import de.ivu.elect.business.sitzberechnung.control.SitzberechnungsalgorithmusFinder;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahlart;
import de.ivu.elect.business.wahl.entity.WahlartSitzberechnungsalgorithmus;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.business.wahl.entity.WahldurchfuehrungConstants;
import de.ivu.elect.jee.presentation.dynamicform.*;

@Specializes
public class WasWahlViewFormBuilder extends CommonWahlViewFormBuilder {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient SitzberechnungsalgorithmusFinder sitzberechnungsalgorithmusFinder;

  public WasWahlViewFormBuilder() {
    super();
  }

  protected boolean isAlgorithmusAuswahlAnzeigen() {
    return true;
  }

  @Override
  protected void addProperties(FormBuilder formBuilder, Wahl wahl, Property wahlartProperty, AbstractDateProperty wahlterminWahldatumProperty, boolean readonly) {
    super.addProperties(formBuilder, wahl, wahlartProperty, wahlterminWahldatumProperty, readonly);

    addSitzberechnungsalgorithmusProperty(formBuilder, wahl, wahlartProperty, readonly);

    addSitzeStimmenProperties(formBuilder, wahl, readonly);
  }

  protected void addSitzberechnungsalgorithmusProperty(FormBuilder formBuilder, Wahl wahl, Property wahlartProperty, boolean readonly) {
    Wahldurchfuehrung wahldurchfuehrung = wahl.castTo(Wahldurchfuehrung.class).getEntity();
    if (isAlgorithmusAuswahlAnzeigen()) {

      Set<WahlartSitzberechnungsalgorithmus> algorithmen = getMoeglicheSitzberechnungsalgorithmen(wahl);
      LambdaEnumProperty<WahlartSitzberechnungsalgorithmus> sitzberechnungsalgorithmusMitLeererAuswahlProperty = wahldurchfuehrung.getProperties()
          .getSitzberechnungsalgorithmusMitLeererAuswahlProperty();
      sitzberechnungsalgorithmusMitLeererAuswahlProperty.setValueFilter(algorithmen::contains);

      sitzberechnungsalgorithmusMitLeererAuswahlProperty.appendObservedPropertyValueChangedConsumer(other -> {
        if (other.equals(wahlartProperty)) {
          if (wahlartProperty instanceof ConversationStoreWahlartSelectOneMenuProperty) {
            Wahlart wahlart = ((ConversationStoreWahlartSelectOneMenuProperty) wahlartProperty).getValue();

            if (wahlart == null || wahlart.getSitzberechnungsalgorithmus() == null) {
              sitzberechnungsalgorithmusMitLeererAuswahlProperty.setValue(WahlartSitzberechnungsalgorithmus.KEIN);
            } else {
              sitzberechnungsalgorithmusMitLeererAuswahlProperty.setValue(wahlart.getSitzberechnungsalgorithmus());
            }
          }
        }
      });

      // Auswahl immer anzeigen, als Fallback ELECT-7448 ELECT-7449 ELECT-7450 ELECT-7451
      formBuilder.addProperty(sitzberechnungsalgorithmusMitLeererAuswahlProperty).withObservedProperty(wahlartProperty).withReadonly(readonly);
    } else {
      formBuilder.addProperty(
          new ReadOnlyStringProperty(getMessage(WahldurchfuehrungConstants.MESSAGE_KEY_SITZBERECHNUNGSALGORITHMUS_EINZAHL), getMessage(wahldurchfuehrung.getSitzberechnungsalgorithmus())));
    }
  }

  protected Set<WahlartSitzberechnungsalgorithmus> getMoeglicheSitzberechnungsalgorithmen(Wahl wahl) {
    return sitzberechnungsalgorithmusFinder.getSitzberechnungsalgorithmen().stream().filter(s -> isNotDeprecatedOderAnWahlGesetzt(s, wahl))
        .map(Sitzberechnungsalgorithmus::getSitzberechnungsalgorithmusEnum).collect(Collectors.toSet());
  }

  private boolean isNotDeprecatedOderAnWahlGesetzt(Sitzberechnungsalgorithmus sitzberechnungsalgorithmus, Wahl wahl) {
    return !sitzberechnungsalgorithmus.getSitzberechnungsalgorithmusEnum().isDeprecated()
        || sitzberechnungsalgorithmus.getSitzberechnungsalgorithmusEnum().equals(wahl.castTo(Wahldurchfuehrung.class).getEntity().getSitzberechnungsalgorithmus());
  }
}
