package de.ivu.elect.presentation.personenpruefung;

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

import de.ivu.elect.business.personenpruefung.boundary.PersonenErneutPruefer;
import de.ivu.elect.business.personenpruefung.boundary.*;
import de.ivu.elect.business.personenpruefung.entity.*;
import de.ivu.elect.jee.presentation.dynamicform.LambdaEnumProperty;
import de.ivu.elect.jee.presentation.redirect.Redirect;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.deltaspike.core.api.scope.ViewAccessScoped;

import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.jee.faces.PreConditionCheck;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.security.AbstractGebietSecurityFilter;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@ViewAccessScoped
@Named(AbstractPersonPruefungKonfigurationSearchView.COMPONENT_NAME)
@View(viewId = AbstractPersonPruefungKonfigurationSearchView.VIEW_ID, useCase = UseCasePermission.PERSON_PRUEFUNG_KONFIGURATION_SEARCH)
public class PersonPruefungKonfigurationSearchView extends AbstractPersonPruefungKonfigurationSearchView {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient PersonenErneutPruefer personenErneutPruefer;

  private boolean bearbeiteteKonflikteErneutPruefen = false;

  @Override
  protected AbstractGebietSecurityFilter<PersonPruefungKonfiguration> getGebietSecurityFilter() {
    return KEIN_GEBIET_SECURITY_FILTER;
  }

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

    return null;
  }

  @Override
  public PersonPruefungKonfigurationSearchParameters getSearchParameters() {
    PersonPruefungKonfigurationSearchParameters searchParameters = super.getSearchParameters();
    searchParameters.getPersonPruefungKonfiguration().setWahl(getSelectedWahl());
    searchParameters.getPersonPruefungKonfiguration().setWahltermin(getSelectedWahltermin());
    return searchParameters;
  }

  @Override
  protected void presetSearchParameters() {
  }

  @Override
  public void addProperties(FormBuilder formBuilder) {
    formBuilder.addProperty(getSearchParameters().getPersonPruefungKonfiguration().getProperties().getNameProperty()).withRequired(false);
    formBuilder.addProperty(createPersonentypProperty()).withRequired(false);
    formBuilder.addProperty(createTypProperty()).withRequired(false);
    formBuilder.addProperty(getSearchParameters().getPersonPruefungKonfiguration().getProperties().getStatusMitLeererAuswahlProperty()).withRequired(false);
  }

  private LambdaEnumProperty<PersonPruefungKonfigurationPersonentyp> createPersonentypProperty() {
    List<PersonPruefungKonfigurationPersonentyp> vorhandenePersonentypen = search.findVorhandenePersonentypen(getSelectedWahltermin(), getSelectedWahl());

    LambdaEnumProperty<PersonPruefungKonfigurationPersonentyp> personentypProperty = getSearchParameters().getPersonPruefungKonfiguration().getProperties().getPersonentypMitLeererAuswahlProperty();
    personentypProperty.setValueFilter(vorhandenePersonentypen::contains);

    return personentypProperty;
  }

  private LambdaEnumProperty<PersonPruefungKonfigurationTyp> createTypProperty() {
    List<PersonPruefungKonfigurationTyp> vorhandeneTypen = search.findVorhandeneTypen(getSelectedWahltermin(), getSelectedWahl());

    LambdaEnumProperty<PersonPruefungKonfigurationTyp> typProperty = getSearchParameters().getPersonPruefungKonfiguration().getProperties().getTypMitLeererAuswahlProperty();
    typProperty.setValueFilter(vorhandeneTypen::contains);

    return typProperty;
  }

  public boolean isBtnErneutPruefenRendered() {
    return hasPermission(UseCasePermission.PERSON_PRUEFUNG_KONFIGURATION_EDIT);
  }

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

  public boolean isBearbeiteteKonflikteErneutPruefen() {
    return bearbeiteteKonflikteErneutPruefen;
  }

  public void setBearbeiteteKonflikteErneutPruefen(boolean bearbeiteteKonflikteErneutPruefen) {
    this.bearbeiteteKonflikteErneutPruefen = bearbeiteteKonflikteErneutPruefen;
  }

  @Redirect
  public String erneutPruefen() {
    Set<PersonPruefungKonfigurationTyp> typen = new HashSet<>();
    Set<PersonPruefungKonfigurationPersonentyp> personentypen = new HashSet<>();
    getSearchResult().stream().forEach(personPruefungKonfiguration -> {
      typen.add(personPruefungKonfiguration.getTyp());
      personentypen.add(personPruefungKonfiguration.getPersonentyp());
    });
    Pair<Integer, Integer> personenUndKonflikteErneutPruefen = personenErneutPruefer.personenErneutPruefen(getSelectedWahltermin(), getSelectedWahl(), typen, personentypen, bearbeiteteKonflikteErneutPruefen);
    if (personenUndKonflikteErneutPruefen.getLeft() == 0) {
      addInfoMessage("person.pruefung.konfiguration.action.erneut.pruefen.keine.person");
    } else {
      addInfoMessage("person.pruefung.konfiguration.action.erneut.pruefen.success", personenUndKonflikteErneutPruefen.getLeft(), personenUndKonflikteErneutPruefen.getRight());
    }
    return getViewId();
  }
}
