
package de.ivu.elect.presentation.wahllokalsystem;

import static java.util.Arrays.asList;

import java.util.Arrays;
import java.util.List;

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

import org.apache.deltaspike.core.api.scope.ViewAccessScoped;

import de.ivu.elect.business.gebietsbaum.boundary.GebietSelectChangeEvent;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.wahl.boundary.WahlSelectChangeEvent;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahllokalsystem.boundary.WahllokalsystemStatusSearchParameters;
import de.ivu.elect.business.wahllokalsystem.entity.WahllokalsystemStatus;
import de.ivu.elect.business.wahllokalsystem.entity.WahllokalsystemStatusDokumentEventType;
import de.ivu.elect.business.wahllokalsystem.entity.WahllokalsystemStatusOnline;
import de.ivu.elect.business.wahllokalsystem.entity.WahllokalsystemStatusProperties;
import de.ivu.elect.business.wahllokalsystem.entity.WahllokalsystemStimmbezirksart;
import de.ivu.elect.jee.entity.EagerLoadingCollector;
import de.ivu.elect.jee.faces.PreConditionCheck;
import de.ivu.elect.jee.presentation.dynamicform.AbstractSelectManyProperty;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.LambdaEnumProperty;
import de.ivu.elect.jee.presentation.dynamicform.LambdaEnumSelectManyProperty;
import de.ivu.elect.jee.presentation.dynamicform.ReadOnlyStringProperty;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.security.AbstractGebietSecurityFilter;
import de.ivu.elect.presentation.wahllokalsystem.table.WahllokalsystemStatusColumnBuilder;

@ViewAccessScoped
@Named(AbstractWahllokalsystemStatusSearchView.COMPONENT_NAME)
@View(viewId = AbstractWahllokalsystemStatusSearchView.VIEW_ID, useCase = UseCasePermission.WAHLLOKALSYSTEM_STATUS_SEARCH)
@OnlineHilfeId(value = "761", mehrfachVergebenOk = true)
public class WahllokalsystemStatusSearchView extends AbstractWahllokalsystemStatusSearchView {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient WahllokalsystemStatusColumnBuilder wahllokalsystemStatusColumnBuilder;

  public WahllokalsystemStatusSearchView() {
    super();
  }

  @PreConditionCheck
  public String checkCondition() {
    if (!isWahlSelected()) {
      return getStartViewId();
    }

    return null;
  }

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

  @Override
  public WahllokalsystemStatusSearchParameters getSearchParameters() {
    WahllokalsystemStatusSearchParameters searchParameters = super.getSearchParameters();
    searchParameters.setWahl(getSelectedWahl());
    searchParameters.setGebiet(getSelectedGebiet());
    return searchParameters;
  }

  @Override
  public void addProperties(FormBuilder formBuilder) {

    WahllokalsystemStatusProperties properties = getSearchParameters().getWahllokalsystemStatus().getProperties();
    formBuilder.addProperty(properties.getAusstattungMitLeererAuswahlProperty()).withRequired(false);

    formBuilder.addProperty(new LambdaEnumSelectManyProperty<>(AbstractSelectManyProperty.CHECKBOX_MENU, getMessage("wahllokalsystem.status.online"), false, getSearchParameters()::setStatusOnline,
        getSearchParameters()::getStatusOnline, WahllokalsystemStatusOnline.class, Arrays.asList(WahllokalsystemStatusOnline.values()), true));

    formBuilder.addProperty(new LambdaEnumProperty<>(getMessage("wahllokalsystem.status.stimmbezirksart"), true, getSearchParameters()::setWahllokalsystemStimmbezirksart,
        getSearchParameters()::getWahllokalsystemStimmbezirksart, WahllokalsystemStimmbezirksart.class, asList(WahllokalsystemStimmbezirksart.values()), false)).withRequired(true);

    List<Wahl> alleWahlenAmTermin = bestimmeAlleWahlenAmTermin();
    if (!alleWahlenAmTermin.isEmpty()) {
      formBuilder.addSeparator("wahllokal.serach.dokument.separator");

      if (alleWahlenAmTermin.size() == 1) {
        formBuilder.addProperty(new ReadOnlyStringProperty("wahllokal.serach.dokument.betrachtete.wahl", alleWahlenAmTermin.iterator().next().getName()));
      } else {
        formBuilder.addProperty(new WahllokalsystemWahlSelectOneMenuProperty(alleWahlenAmTermin, getSearchParameters()));
      }

      for (WahllokalsystemStatusDokumentEventType value : WahllokalsystemStatusDokumentEventType.values()) {
        if (value.isMeldungVomWls()) {
          formBuilder.addProperty(new WahllokalSystemDokumentBooleanFilterKriteriumProperty(value, getSearchParameters(), messages));
        }
      }
    }

  }

  private List<Wahl> bestimmeAlleWahlenAmTermin() {
    return getSelectedWahl().getWahltermin().getWahlenSortiertNachPosition();

  }

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

  @Override
  public void presetSearchParameters() {

  }

  @Override
  public void onWahlSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) WahlSelectChangeEvent event) {
    resetSearchResult(); // Suchergebnis zurücksetzen, weil sonst beim Wechseln der(s) Wahl(termins) nicht das Ergebnis gelöscht wird
  }

  // NOTE ELECTMUC-882, dass Suchparameter ggf. (!) vom ausgewählten Gebiet abhängig sind. Wird dieses gewechselt müssen
  // NICHT alle Werte des Suchparameter, zumindest aber die Pagination, zurückgesetzt werden!
  public void onGebietSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) GebietSelectChangeEvent event) {
    resetSearchResult(); // Suchergebnis zurücksetzen, weil sonst beim Wechseln der(s) Wahl(termins) nicht das Ergebnis gelöscht wird
  }

  public String getGebietName() {
    return getSelectedGebietNameFormatted();
  }

  @Override
  public boolean isBtnGoBackRendered() {
    return viewStackContainsOtherViewsAndShouldNotReset();
  }

  @Override
  public EagerLoadingCollector<WahllokalsystemStatus> getEagerLoadingCollector() {
    EagerLoadingCollector<WahllokalsystemStatus> eagerLoadingCollector = super.getEagerLoadingCollector();
    wahllokalsystemStatusColumnBuilder.collectEagerLoadings(eagerLoadingCollector);
    return eagerLoadingCollector;
  }
}
