
package de.ivu.elect.presentation.kandidatur;

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.kandidatur.entity.Direktkandidatur;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
import de.ivu.elect.business.wahlvorschlag.boundary.DirektkandidatEdit;
import de.ivu.elect.business.wahlvorschlag.boundary.EinzelbewerberWahlvoschlagEdit;
import de.ivu.elect.business.wahlvorschlag.boundary.WahlvorschlagZulassungsvorschlagSetzer;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagStatus;
import de.ivu.elect.business.wahlvorschlag.entity.ZulassungsvorschlagSetzerErgebnis;
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.redirect.Redirect;
import de.ivu.elect.jee.presentation.search.AbstractSearchParameters;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.kandidatur.table.DirektkandidaturColumnBuilder;
import de.ivu.elect.presentation.security.AbstractGebietSecurityFilter;
import de.ivu.elect.presentation.wahl.CurrentWahlZulassungspruefungExtended;
import de.ivu.elect.presentation.wahlvorschlag.ListeSearchView;
import de.ivu.elect.presentation.wahlvorschlag.WahlvorschlagSearchViewResolver;
import de.ivu.elect.presentation.wahlvorschlag.WahlvorschlagSearchViewResolverTarget;

@OnlineHilfeId(value = "443", mehrfachVergebenOk = true)
@Named(AbstractDirektkandidaturSearchView.COMPONENT_NAME)
public class DirektkandidaturSearchView extends AbstractDirektkandidaturSearchView implements WahlvorschlagSearchViewResolverTarget {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient CurrentWahlZulassungspruefungExtended currentWahlZulassungspruefung;

  @Inject
  private transient WahlvorschlagZulassungsvorschlagSetzer wahlvorschlagZulassungsvorschlagSetzer;

  @Inject
  private transient WahlvorschlagSearchViewResolver wahlvorschlagSearchViewResolver;

  @Inject
  private transient DirektkandidatEdit direktkandidatEdit;

  @Inject
  private transient EinzelbewerberWahlvoschlagEdit einzelbewerberWahlvoschlagEdit;

  @Inject
  private transient DirektkandidaturColumnBuilder direktkandidaturColumnBuilder;

  private List<Kandidatur> searchResultIncludingErsatzkandidaturen;

  public DirektkandidaturSearchView() {
    super();
  }

  @PreConditionCheck
  public String checkCondition() {
    return wahlvorschlagSearchViewResolver.checkCondition(VIEW_ID);
  }

  @Override
  public void preRenderView() {
    // Do nothing...
  }

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

  public List<Kandidatur> getSearchResultIncludingErsatzkandidaturen() {
    List<Direktkandidatur> kandidaturen = getSearchResult();

    if (searchResultIncludingErsatzkandidaturen == null) {
      searchResultIncludingErsatzkandidaturen = new ArrayList<>();

      for (Kandidatur kandidatur : kandidaturen) {
        searchResultIncludingErsatzkandidaturen.add(kandidatur);
        searchResultIncludingErsatzkandidaturen.addAll(kandidatur.getUntergeordneteErsatzkandidaturen());
      }

      searchResultIncludingErsatzkandidaturen = getEagerLoadingCollector().eagerLoad(searchResultIncludingErsatzkandidaturen);
    }

    return searchResultIncludingErsatzkandidaturen;
  }

  @Override
  public int getSearchResultSize() {
    return getSearchResultIncludingErsatzkandidaturen().size();
  }

  @Override
  public List<Direktkandidatur> getSearchResult() {
    // NOTE ELECT-1570, Gebiet muss immer gesetzt werden, da der GebietSelectChangeEvent nicht mehr gefeuert wird,
    // sobald auf einer über-/untergeordneten Ebene eines anderen Typs (bspw. Liste) navigiert wird.
    searchParameters.setGebiet(getSelectedGebiet());

    return super.getSearchResult();
  }

  @Override
  public void setSearchReady() {
    // ELECT-4131

    resetSearchResult();
    resetSearchParametersModel();
    resetSearchResultIncludingErsatzkandidaturen();
    super.setSearchReady();
  }

  @Override
  public void resetSearchResult() {
    resetSearchResultIncludingErsatzkandidaturen();
    resetSearchParametersModel();
    super.resetSearchResult();
  }

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

  private void resetSearchResultIncludingErsatzkandidaturen() {
    searchResultIncludingErsatzkandidaturen = null;
  }

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

  @Override
  public String getWahlvorschlagStatusOffenMessage() {
    return getMessage(WahlvorschlagStatus.OFFEN);
  }

  @Override
  @Redirect
  @UseCaseSecure(UseCasePermission.WAHLVORSCHLAG_QS_FUER_ALLE_ZULASSUNGSVORSCHLAG_SETZEN)
  public String fuerAlleZulassungsvorschlagSetzen() {
    ZulassungsvorschlagSetzerErgebnis result = wahlvorschlagZulassungsvorschlagSetzer.fuerAlleZulassungsvorschlagSetzen(getSelectedGebiet());

    String msgKeyWahlvorschlagZugelassen = "wahlvorschlag.search.action.fuer.alle.zulassungsvorschlag.setzen.success.message.wahlvorschlag.zugelassen.plural";
    if (result.getWahlvorschlaegeZugelassen() == 1) {
      msgKeyWahlvorschlagZugelassen = "wahlvorschlag.search.action.fuer.alle.zulassungsvorschlag.setzen.success.message.wahlvorschlag.zugelassen.singular";
    }
    addInfoMessage(msgKeyWahlvorschlagZugelassen, result.getWahlvorschlaegeZugelassen());

    if (isWahlMitListengebieten()) {
      String msgKeyListenkandidaturZugelassen = "wahlvorschlag.search.action.fuer.alle.zulassungsvorschlag.setzen.success.message.listenkandidatur.zugelassen.plural";
      if (result.getListenkandidaturenZugelassen() == 1) {
        msgKeyListenkandidaturZugelassen = "wahlvorschlag.search.action.fuer.alle.zulassungsvorschlag.setzen.success.message.listenkandidatur.zugelassen.singular";
      }
      addInfoMessage(msgKeyListenkandidaturZugelassen, result.getListenkandidaturenZugelassen());
    }

    return getViewId();
  }

  private boolean isWahlMitListengebieten() {
    if (getSelectedGebiet() == null) {
      return false;
    }

    return getSelectedGebiet().getWahl().isWahlMitListengebieten();
  }

  public boolean isBtnAlleDirektkandidaturenLoeschenRendered() {
    return hasPermission(UseCasePermission.DIREKTKANDIDATUR_DELETE);
  }

  public boolean isBtnAlleDirektkandidaturenLoeschenDisabled() {
    return isEmptySearchResultDisplayed() || !isBearbeitenRechtAufAktuellemGebietVorhanden();
  }

  protected Collection<Direktkandidat> getSearchResultDirektkandidaten() {
    List<Direktkandidat> result = new ArrayList<>();
    for (Direktkandidatur kandidatur : getSearchResult()) {
      result.add(kandidatur.getDirektkandidat());
    }
    return result;
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.DIREKTKANDIDATUR_DELETE)
  public String alleDirektkandidaturenLoeschen() {
    Collection<Direktkandidat> direktkandidaten = getSearchResultDirektkandidaten();

    for (Direktkandidat direktkandidat : direktkandidaten) {
      if (direktkandidat.isEinzelbewerber()) {
        einzelbewerberWahlvoschlagEdit.delete(direktkandidat);
      } else {
        direktkandidatEdit.delete(direktkandidat);
      }
    }

    addMessageDeleteAllSuccess();

    resetSearchResult();

    return VIEW_ID;
  }

  private void addMessageDeleteAllSuccess() {
    addInfoMessage("entity.edit.action.delete.all.success.message", entityMeta.getMehrzahlMessage());
  }

  @Override
  public void presetSearchParameters() {
    searchParameters.setGebiet(getSelectedGebiet());
  }

  @Override
  public void addProperties(FormBuilder formBuilder) {
    String wildcardTooltip = getMessage(AbstractSearchParameters.WILDCARD_TOOLTIP_MSG_KEY);

    formBuilder.addProperty(getSearchParameters().getKennwortProperty()).withTooltip(wildcardTooltip);
    formBuilder.addProperty(getSearchParameters().getKurznameProperty()).withTooltip(wildcardTooltip);

    if (currentWahlZulassungspruefung.isZulassungBearbeitbar()) { // ELECT-7087
      formBuilder.addProperty(getSearchParameters().getKandidaturStatusProperty());
    }

    formBuilder.addProperty(getSearchParameters().getTitelProperty()).withTooltip(wildcardTooltip);
    formBuilder.addProperty(getSearchParameters().getFamiliennameProperty()).withTooltip(wildcardTooltip);
    formBuilder.addProperty(getSearchParameters().getVornameProperty()).withTooltip(wildcardTooltip);
  }

  public boolean isBtnListenAnzeigenRendered() {
    return wahlvorschlagSearchViewResolver.getViewIdOrDefault().contains(ListeSearchView.VIEW_ID);
  }

  public boolean isBtnListenAnzeigenDisabled() {
    return false;
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.LISTE_SEARCH)
  public String listenAnzeigen() {
    return ListeSearchView.VIEW_ID;
  }

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

    return eagerLoadingCollector;
  }
}
