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

import de.ivu.elect.business.wahl.boundary.WahlExtendedDAO;
import de.ivu.elect.business.wahl.boundary.WahlartConversationStore;
import de.ivu.elect.business.wahl.entity.*;
import de.ivu.elect.jee.presentation.dynamicform.*;
import de.ivu.elect.presentation.ViewFormBuilder;
import org.apache.commons.lang3.StringUtils;

import javax.faces.validator.LongRangeValidator;
import javax.inject.Inject;
import java.util.List;

import static java.util.Arrays.asList;

public class WahlViewFormBuilder extends ViewFormBuilder {

  @Inject
  private transient WahlExtendedDAO wahlExtendedDAO;

  private static final long serialVersionUID = 1L;

  public WahlViewFormBuilder() {
    super();
  }

  public void addProperties(FormBuilder formBuilder, Wahl wahl, AbstractDateProperty wahlterminWahldatumProperty) {
    addProperties(formBuilder, wahl, wahlterminWahldatumProperty, false);
  }

  public void addProperties(FormBuilder formBuilder, Wahl wahl, AbstractDateProperty wahlterminWahldatumProperty, boolean readonly) {
    Property wahlartNameProperty = new ReadOnlyStringProperty(getMessage(WahlartConstants.MESSAGE_KEY_ENTITY_EINZAHL), getNameWahlart(wahl.getWahlart()));
    formBuilder.addProperty(wahlartNameProperty).readonly();
    addProperties(formBuilder, wahl, wahlartNameProperty, wahlterminWahldatumProperty, readonly);
  }

  protected String getNameWahlart(Wahlart wahlart) {
    return wahlart.getNameGuiEindeutig();
  }

  public void addProperties(FormBuilder formBuilder, Wahl wahl, WahlartConversationStore wahlartContextParameter, List<Wahlart> wahlarten, AbstractDateProperty wahlterminWahldatumProperty) {
    addProperties(formBuilder, wahl, wahlartContextParameter, wahlarten, wahlterminWahldatumProperty, false);
  }

  public void addProperties(FormBuilder formBuilder, Wahl wahl, WahlartConversationStore wahlartContextParameter, List<Wahlart> wahlarten,
      AbstractDateProperty wahlterminWahldatumProperty, boolean readonly) {
    Property wahlartProperty = new ConversationStoreWahlartSelectOneMenuProperty(wahlartContextParameter, wahlarten);

    formBuilder.addProperty(wahlartProperty).required().withReadonly(readonly);

    addProperties(formBuilder, wahl, wahlartProperty, wahlterminWahldatumProperty, readonly);
  }

  protected void addProperties(FormBuilder formBuilder, Wahl wahl, Property wahlartProperty, AbstractDateProperty wahlterminWahldatumProperty, boolean readonly) {
    var isAufgeteilt = isWahlAufgeteiltOderBerichtetAn(wahl); // ELECT-16933

    addNameProperty(formBuilder, wahl, readonly || isAufgeteilt);

    addKurznameProperty(formBuilder, wahl, wahlartProperty, readonly || isAufgeteilt);

    addKennzeichenProperty(formBuilder, wahl, wahlartProperty, readonly || isAufgeteilt);

    addWahlCreateDokumenteUebernehmenProperty(formBuilder, wahl, wahlartProperty, readonly || isAufgeteilt);

    addWahlgangProperty(formBuilder, wahl, readonly || isAufgeteilt);

    addFarbeProperty(formBuilder, wahl, wahlartProperty, readonly || isAufgeteilt);

    addAnzahlStimmzettelProperty(formBuilder, wahl, wahlartProperty, readonly);
  }

  private void addNameProperty(FormBuilder formBuilder, Wahl wahl, boolean readonly) {
    formBuilder.addProperty(wahl.getProperties().getNameProperty()).withReadonly(readonly);
  }

  private void addKurznameProperty(FormBuilder formBuilder, Wahl wahl, Property wahlartProperty, boolean readonly) {
    WahlProperties.KurznameProperty kurznameProperty = wahl.getProperties().getKurznameProperty();
    kurznameProperty.appendObservedPropertyValueChangedConsumer(other -> {
      if (other.equals(wahlartProperty)) {
        if (wahlartProperty instanceof ConversationStoreWahlartSelectOneMenuProperty) {
          String kurzname = ((ConversationStoreWahlartSelectOneMenuProperty) wahlartProperty).getValue().getKurzname();
          if (StringUtils.isNotBlank(kurzname)) {
            kurznameProperty.setValue(kurzname);
          }
        }
      }
    });
    formBuilder.addProperty(kurznameProperty).withObservedProperty(wahlartProperty).withReadonly(readonly);
  }

  private void addKennzeichenProperty(FormBuilder formBuilder, Wahl wahl, Property wahlartProperty, boolean readonly) {
    WahlProperties.KennzeichenProperty kennzeichenProperty = wahl.getProperties().getKennzeichenProperty();
    kennzeichenProperty.appendObservedPropertyValueChangedConsumer(other -> {
      if (other.equals(wahlartProperty)) {
        if (wahlartProperty instanceof ConversationStoreWahlartSelectOneMenuProperty) {
          String kennzeichen = ((ConversationStoreWahlartSelectOneMenuProperty) wahlartProperty).getValue().getKennzeichen();
          if (StringUtils.isNotBlank(kennzeichen)) {
            kennzeichenProperty.setValue(kennzeichen);
          }
        }
      }
    });

    formBuilder.addProperty(kennzeichenProperty).withObservedProperty(wahlartProperty).withReadonly(readonly);
  }

  private void addWahlCreateDokumenteUebernehmenProperty(FormBuilder formBuilder, Wahl wahl, Property wahlartProperty, boolean readonly) {
    if (!wahl.isPersistent() /*Auswahl der Dokumentvorlagen nur beim Anlegen relevant*/) {
      LambdaEnumProperty<WahlCreateDokumenteUebernehmen> wahlCreateDokumenteUebernehmenProperty = new LambdaEnumProperty<>(
        getMessage("wahl.create.dokumentvorlagen.uebernehmen"), true,
        wahl::setWahlCreateDokumenteUebernehmen, wahl::getWahlCreateDokumenteUebernehmen, WahlCreateDokumenteUebernehmen.class,
        asList(WahlCreateDokumenteUebernehmen.values()));

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

            if (wahlart == null || !wahlart.getDokumentvorlagen().isVorlagenVorhanden()) {
              wahlCreateDokumenteUebernehmenProperty.setValue(WahlCreateDokumenteUebernehmen.NICHT_UBERNEHMEN);
            } else {
              wahlCreateDokumenteUebernehmenProperty.setValue(WahlCreateDokumenteUebernehmen.AUS_WAHLART_UEBEREHMEN);
            }
          }
        }
      });

      formBuilder.addProperty(wahlCreateDokumenteUebernehmenProperty).withObservedProperty(wahlartProperty).withReadonly(readonly);
    }
  }

  private void addWahlgangProperty(FormBuilder formBuilder, Wahl wahl, boolean readonly) {
    formBuilder.addProperty(wahl.getProperties().getWahlgangMitLeererAuswahlProperty()).withReadonly(readonly);
  }

  protected void addFarbeProperty(FormBuilder formBuilder, Wahl wahl, Property wahlartProperty, boolean readonly) {
    formBuilder.addProperty(new AutoUpdateFarbeProperty(wahl)).withObservedProperty(wahlartProperty).withReadonly(readonly);
  }

  private void addAnzahlStimmzettelProperty(FormBuilder formBuilder, Wahl wahl, Property wahlartProperty, boolean readonly) {
    WahlProperties.AnzahlStimmzettelProperty anzahlStimmzettelProperty = wahl.getProperties().getAnzahlStimmzettelProperty();
    anzahlStimmzettelProperty.appendObservedPropertyValueChangedConsumer(other -> {
      if (other.equals(wahlartProperty)) {
        if (wahlartProperty instanceof ConversationStoreWahlartSelectOneMenuProperty) {
          Long anzahlStimmzettel = ((ConversationStoreWahlartSelectOneMenuProperty) wahlartProperty).getValue().getAnzahlStimmzettel();
          if (anzahlStimmzettel != null) {
            anzahlStimmzettelProperty.setValue(anzahlStimmzettel);
          }
        }
      }
    });
    formBuilder.addProperty(anzahlStimmzettelProperty).withObservedProperty(wahlartProperty).withReadonly(readonly).withValidator(new LongRangeValidator(1000L /*willkürlich, vgl. WahlartViewFormBuilder*/, 0L) );
  }

  protected boolean isWahlAufgeteiltOderBerichtetAn(Wahl wahl) {
    return wahl != null && wahl.isWahlAufgeteiltOderBerichtetAn(wahlExtendedDAO);
  }
}
