
package de.ivu.elect.presentation.stimmeingabe;

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

import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.inject.Inject;
import javax.inject.Named;

import de.ivu.elect.business.gebietsbaum.boundary.GebietSelectChangeEvent;
import de.ivu.elect.business.gebietsbaum.boundary.WahldurchfuehrungsgebietSessionSelect;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.stimmeingabe.boundary.ErgebniseingangKonfiguration;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingabestufe;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;
import de.ivu.elect.business.stimmeingabe.entity.ErgebniseingangConstants;
import de.ivu.elect.business.stimmeingabe.entity.ErgebniseingangProperties;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingangsart;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingangsfehlerstatus;
import de.ivu.elect.business.wahl.boundary.WahldurchfuehrungSessionSelect;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.jee.entity.EagerLoadingCollector;
import de.ivu.elect.jee.faces.PreConditionCheck;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.LambdaBooleanProperty;
import de.ivu.elect.jee.presentation.dynamicform.LambdaEnumSelectManyProperty;
import de.ivu.elect.jee.presentation.dynamicform.LambdaStringProperty;
import de.ivu.elect.jee.presentation.dynamicform.LambdaTimestampBetweenProperty;
import de.ivu.elect.jee.presentation.dynamicform.LambdaTimestampProperty;
import de.ivu.elect.presentation.ergebnis.ErgebnisStatusInfo;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.security.AbstractGebietSecurityFilter;
import de.ivu.elect.presentation.stimmeingabe.table.ErgebniseingangColumnBuilder;

@OnlineHilfeId("344")
@Named(AbstractErgebniseingangSearchView.COMPONENT_NAME)
public class ErgebniseingangSearchView extends AbstractErgebniseingangSearchView implements StimmeingabeErfassenViewHavingHeader {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient WahldurchfuehrungSessionSelect wahldurchfuehrungSessionSelect;

  @Inject
  private transient WahldurchfuehrungsgebietSessionSelect wahldurchfuehrungsgebietSessionSelect;

  @Inject
  private transient ErgebniseingangKonfiguration ergebniseingangKonfiguration;

  @Inject
  private transient ErgebniseingangColumnBuilder ergebniseingangColumnBuilder;

  public ErgebniseingangSearchView() {
    super();
  }

  @PreConditionCheck
  public String checkCondition() {
    if (!isWahldurchfuehrungSelected()) {
      addErrorMessage("wahl.selected.missing");

      return getStartViewId();
    }

    return null;
  }

  @Override
  protected AbstractGebietSecurityFilter<Ergebniseingang> getGebietSecurityFilter() {
    return AbstractGebietSecurityFilter.createEntityMitGebietSecurityFilter(getEinsehenGebietSecurity());
  }

  /**
   * @deprecated To be removed...
   * @see ErgebniseingangSearchView#initSearchParametersByContext
   */
  @Deprecated
  @Override
  public void presetSearchParameters() {
    // To be removed...
  }

  @Override
  protected void initSearchParametersByContext() {
    super.initSearchParametersByContext();

    Wahldurchfuehrung wahldurchfuehrung = getSelectedWahldurchfuehrung();

    getSearchParameters().setWahldurchfuehrung(wahldurchfuehrung);

    if (wahldurchfuehrung != null) {
      getSearchParameters().setErgebniseingangsart(wahldurchfuehrung.getErgebniseingangsart());
    }

    getSearchParameters().setWahldurchfuehrungsgebiet(getSelectedWahldurchfuehrungsgebiet());
  }

  @Override
  public void addProperties(FormBuilder formBuilder) {
    Wahldurchfuehrung wahldurchfuehrung = getSelectedWahldurchfuehrung();

    boolean ergebniseingangsartRendered = ergebniseingangKonfiguration.isWechselErgebniseingangsartenUnterstuetzt(wahldurchfuehrung)
        || getSearchParameters().getErgebniseingangsart() != null && !((Collection<Ergebniseingangsart>) ergebniseingangKonfiguration
        .collectErgebniseingangsarten(wahldurchfuehrung))
        .contains(getSearchParameters().getErgebniseingangsart());

    if (ergebniseingangsartRendered) {

      ErgebniseingangProperties.ErgebniseingangsartMitLeererAuswahlProperty ergebniseingangsartProperty = getSearchParameters()
          .getErgebniseingangProperties().getErgebniseingangsartMitLeererAuswahlProperty();
      ergebniseingangsartProperty.setRequired(false);
      formBuilder.addProperty(ergebniseingangsartProperty).readonly();
    }

    List<Ergebniseingabestufe> ergebniseingabestufen = ergebniseingangKonfiguration.collectErgebniseingabestufen(wahldurchfuehrung);
    boolean ergebniseingabestufeRendered = ergebniseingangKonfiguration.isWechselErgebniseingabestufenUnterstuetzt(wahldurchfuehrung) || !getSearchParameters().getErgebniseingabestufen().isEmpty()
        && getSearchParameters().getErgebniseingabestufen().stream().anyMatch(ergebniseingabestufe -> !ergebniseingabestufen.contains(ergebniseingabestufe));

    if (ergebniseingabestufeRendered) {

      LambdaEnumSelectManyProperty<Ergebniseingabestufe> ergebniseingabestufenProperty = new LambdaEnumSelectManyProperty<>(
          LambdaEnumSelectManyProperty.CHECKBOX_MENU, getMessage(ErgebniseingangConstants.MESSAGE_KEY_ERGEBNISEINGABESTUFE_EINZAHL),
          false, getSearchParameters()::setErgebniseingabestufen, getSearchParameters()::getErgebniseingabestufen, Ergebniseingabestufe.class,
          new ArrayList<>(ergebniseingabestufen));
      formBuilder.addProperty(ergebniseingabestufenProperty);
    }

    List<Ergebniseingangsfehlerstatus> ergebniseingangsfehlerstatus = ergebniseingangKonfiguration.collectErgebniseingangsfehlerstatus(wahldurchfuehrung);

    LambdaEnumSelectManyProperty<Ergebniseingangsfehlerstatus> ergebniseingangsfehlerstatusProperty = new LambdaEnumSelectManyProperty<>(
        LambdaEnumSelectManyProperty.CHECKBOX_MENU,
        getMessage(ErgebniseingangConstants.MESSAGE_KEY_ERGEBNISEINGANGSFEHLERSTATUS_EINZAHL), false, getSearchParameters()::setErgebniseingangsfehlerstatus,
        getSearchParameters()::getErgebniseingangsfehlerstatus,
        Ergebniseingangsfehlerstatus.class, new ArrayList<>(ergebniseingangsfehlerstatus));


    formBuilder.addProperty(ergebniseingangsfehlerstatusProperty);


    formBuilder.addProperty(new LambdaTimestampBetweenProperty(getMessage("ergebniseingang.suche.zeitpunt.zwischen"), new LambdaTimestampProperty(getMessage(
        "ergebniseingang.suche.zeitpunt.von"), false,
        searchParameters::setZeitpunktVon
        , searchParameters::getZeitpunktVon), new LambdaTimestampProperty(getMessage("ergebniseingang.suche.zeitpunt.bis"), false,
        searchParameters::setZeitpunktBis, searchParameters::getZeitpunktBis)));


    formBuilder.addProperty(new LambdaStringProperty(getMessage("ergebniseingang.fehler.beschreibung.column"), false, getSearchParameters()::setFehlerWarnungen,
        getSearchParameters()::getFehlerWarnungen, 0, 4096));


    formBuilder.addProperty(new LambdaBooleanProperty(messages.getMessageForMessageKey("ergebniseingang.nur.letzten.eingang.pro.gebiet.anzeigen"), false,
        getSearchParameters()::setNurLetztenEingangProGebietAnzeigen, getSearchParameters()::isNurLetztenEingangProGebietAnzeigen));

  }

  @Override
  public String getGebietName() {
    return formatGebietName(getSelectedWahldurchfuehrungsgebiet());
  }

  @Override
  public ErgebnisStatusInfo getErgebnisStatusInfo() {
    return ErgebnisStatusInfo.EMPTY; // nichts anzeigen
  }

  private boolean isWahldurchfuehrungSelected() {
    return wahldurchfuehrungSessionSelect.isSelected();
  }

  private Wahldurchfuehrung getSelectedWahldurchfuehrung() {
    return wahldurchfuehrungSessionSelect.getEntity();
  }

  private boolean isWahldurchfuehrungsgebietSelected() {
    return wahldurchfuehrungsgebietSessionSelect.isSelected();
  }

  private Wahldurchfuehrungsgebiet getSelectedWahldurchfuehrungsgebiet() {
    return wahldurchfuehrungsgebietSessionSelect.getEntity();
  }

  public void onGebietSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) GebietSelectChangeEvent event) {
    reset();
    resetSearchResult();
  }

  @Override
  public EagerLoadingCollector getEagerLoadingCollector() {
    EagerLoadingCollector eagerLoadingCollector = super.getEagerLoadingCollector();
    ergebniseingangColumnBuilder.collectEagerLoadings(eagerLoadingCollector);

    return eagerLoadingCollector;
  }

  public boolean isBtnDokumentRendered() {
    return hasPermission(UseCasePermission.DOKUMENT_ERZEUGEN_NIEDERSCHRIFT);
  }

  public boolean isBtnDokumentDisabled() {
    return isEmptySearchResultDisplayed();
  }

}
