
package de.ivu.elect.presentation.wahlvorschlag;

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

import javax.annotation.Nullable;
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.entity.Gebiet;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
import de.ivu.elect.business.wahlvorschlag.boundary.EinzelbewerberWahlvoschlagEdit;
import de.ivu.elect.business.wahlvorschlag.boundary.ListeEdit;
import de.ivu.elect.business.wahlvorschlag.boundary.WahlvorschlagUnterstuetzerAnzahlAbrufResolver;
import de.ivu.elect.business.wahlvorschlag.boundary.WahlvorschlagUnterstuetzerImporter;
import de.ivu.elect.business.wahlvorschlag.boundary.WahlvorschlagZulassungsvorschlagSetzer;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.ListeProperties;
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.DirektkandidaturSearchView;
import de.ivu.elect.presentation.security.AbstractGebietSecurityFilter;
import de.ivu.elect.presentation.wahl.CurrentWahlZulassungspruefungExtended;
import de.ivu.elect.presentation.wahlvorschlag.form.ListeAuchUebergeordneteListenProperty;
import de.ivu.elect.presentation.wahlvorschlag.table.ListeColumnBuilder;

@OnlineHilfeId(value = "443", mehrfachVergebenOk = true)
@Named(AbstractListeSearchView.COMPONENT_NAME)
public class ListeSearchView extends AbstractListeSearchView 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 WahlvorschlagUnterstuetzerImporter wahlvorschlagUnterstuetzerImporter;

  @Inject
  private transient WahlvorschlagUnterstuetzerAnzahlAbrufResolver wahlvorschlagUnterstuetzeranzahlAbrufResolver;

  @Inject
  private transient ListeEdit listeEdit;

  @Inject
  private transient EinzelbewerberWahlvoschlagEdit einzelbewerberWahlvoschlagEdit;

  @Inject
  private transient ListeColumnBuilder listeColumnBuilder;

  public ListeSearchView() {
    super();
  }

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

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

  public String getPageTitle() {
    return getMessage("liste.search.page.title");
  }

  public String getPageHeader() {
    return getMessage("liste.search.page.header", getGebietName());
  }

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

  @Override
  public List<Liste> 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. Direktkandidat) navigiert wird.
    presetSearchParameters();

    return super.getSearchResult();
  }

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

    resetSearchParametersModel();
    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());

    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();
  }

  public boolean isBtnAlleListenLoeschenRendered() {
    return hasPermission(UseCasePermission.LISTE_DELETE);
  }

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

  public String getBtnAlleListenLoeschenLabel() {
    return getMessage("entity.edit.action.delete.all.entities", entityMeta.getMehrzahlMessage());
  }

  public boolean isBtnUnterstuetzerAbrufenRendered() {
    return wahlvorschlagUnterstuetzeranzahlAbrufResolver.getUnterstuetzerAnzahlAvailability(getSelectedWahl()).isAvailable() && hasPermission(UseCasePermission.UNTERSTUETZER_ANZAHL_IMPORT);
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.LISTE_DELETE)
  public String alleListenLoeschen() {
    Collection<Liste> listen = getSearchResult();

    for (Liste liste : listen) {
      if (liste.isEinzelbewerber()) {
        einzelbewerberWahlvoschlagEdit.delete(liste);
      } else {
        listeEdit.delete(liste);
      }
    }

    addMessageDeleteAllSuccess();

    resetSearchResult();

    return VIEW_ID;
  }

  public boolean isBtnDirektkandidatenAnzeigenRendered() {
    return wahlvorschlagSearchViewResolver.getViewIdOrDefault().contains(DirektkandidaturSearchView.VIEW_ID);
  }

  public boolean isBtnDirektkandidatenAnzeigenDisabled() {
    return false;
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.DIREKTKANDIDATUR_SEARCH)
  public String direktkandidatenAnzeigen() {
    return DirektkandidaturSearchView.VIEW_ID;
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.UNTERSTUETZER_ANZAHL_IMPORT)
  public String unterstuetzerAbrufen() {
    this.wahlvorschlagUnterstuetzerImporter.importUnterstuetzer(getSelectedWahl().getPk());

    return VIEW_ID;
  }

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

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

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

  @Override
  public void addProperties(FormBuilder formBuilder) {
    ListeProperties listeProperties = getSearchParameters().getListe().getProperties();

    String wildcardTooltip = getMessage(AbstractSearchParameters.WILDCARD_TOOLTIP_MSG_KEY);

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

    if (currentWahlZulassungspruefung.isZulassungBearbeitbar()) { // ELECT-7087
      formBuilder.addProperty(listeProperties.getWahlvorschlagStatusMitLeererAuswahlProperty()).withRequired(false);
    }

    if (isUebergeodneteGebieteIstAuchListenwahlgebiet()) {
      formBuilder.addProperty(new ListeAuchUebergeordneteListenProperty(getSearchParameters()));
    }
  }

  private boolean isUebergeodneteGebieteIstAuchListenwahlgebiet() {
    if (isGebietSelected()) {
      Gebiet gebiet = getSelectedGebiet().getUebergeordnetesGebiet();

      while (gebiet != null) {
        if (gebiet.isListenwahlgebiet()) {
          return true;
        }

        gebiet = gebiet.getUebergeordnetesGebiet();
      }
    }

    return false;
  }

  public List<String> getDialogTemplates() {
    return new ArrayList<>(); // ELECT-10224
  }

  @Override
  public EagerLoadingCollector getEagerLoadingCollector() {
    EagerLoadingCollector eagerLoadingCollector = super.getEagerLoadingCollector();
    listeColumnBuilder.collectEagerLoadings(eagerLoadingCollector);
    return eagerLoadingCollector;
  }

  public boolean isBtnGebietHoeherRendered() {
    return false;
  }

  public String getGebietHoeherLabel() {
    return getMessage("liste.search.gebiet.hoher.label");
  }

  @Redirect
  @Nullable
  public String gebietHoeher() {
    return null;
  }
}
