
package de.ivu.elect.presentation.kandidatur;

import static org.apache.commons.lang3.StringUtils.defaultString;

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

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

import de.ivu.elect.business.gebietsbaum.entity.EntityMitGebiet;
import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturEdit;
import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturSearchParameters;
import de.ivu.elect.business.kandidatur.boundary.WaehlerBenannteKandidaturKonfiguration;
import de.ivu.elect.business.kandidatur.entity.Ersatzkandidatur;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.kandidatur.entity.ListenkandidaturConstants;
import de.ivu.elect.business.pruefung.boundary.ZulassungPruefer;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
import de.ivu.elect.business.wahlvorschlag.boundary.ListeConversationSelect;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.ListeProperties;
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.ReadOnlyLongProperty;
import de.ivu.elect.jee.presentation.redirect.Redirect;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.kandidatur.table.ListenkandidaturColumnBuilder;
import de.ivu.elect.presentation.pruefung.ZulassungPrueferRequestScope;
import de.ivu.elect.presentation.security.AbstractGebietSecurityFilter;
import de.ivu.elect.presentation.wahlvorschlag.ListeSearchView;

@OnlineHilfeId("261")
@Named(ListenkandidaturSearchView.COMPONENT_NAME)
public class ListenkandidaturSearchView extends AbstractListenkandidaturSearchView {

  private static final long serialVersionUID = 1L;

  public static final String PARENT_VIEW_ID = ListeSearchView.VIEW_ID;

  private List<Kandidatur> searchResultIncludingErsatzkandidaturen;

  @Inject
  private transient ZulassungPrueferRequestScope zulassungPrueferRequestScope;

  @Inject
  private transient ListeConversationSelect listeConversationSelect;

  @Inject
  private transient ListenkandidaturEdit listenkandidaturEdit;

  @Inject
  private transient ListenkandidaturColumnBuilder listenkandidaturColumnBuilder;

  @Inject
  private transient WaehlerBenannteKandidaturKonfiguration waehlerBenannteKandidaturKonfiguration;

  private String kandidaturStatusBemerkung;

  public ListenkandidaturSearchView() {
    super();
  }

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

      return ListeSearchView.VIEW_ID;
    }

    return null;
  }

  @Override
  public boolean isSupportsLazyLoading() {
    return false; // ELECT-6623 update in xhtml-Seite hat nicht funktioniert...?
  }

  public String getPageTitle() {
    String msgKeyEntityMehrzahl = ListenkandidaturConstants.MESSAGE_KEY_ENTITY_MEHRZAHL;

    if (isWaehlerBenannteListeSelected()) {
      msgKeyEntityMehrzahl = WaehlerBenannteKandidaturKonfiguration.MSG_KEY_WAEHLER_BENANNTE_LISTE_MEHRZAHL;
    }

    return getMessage("entity.search.page.title", getMessage(msgKeyEntityMehrzahl));
  }

  public String getPageHeader() {
    if (isWaehlerBenannteListeSelected()) {
      return getMessage("entity.mit.gebiet.search.page.header", getMessage(WaehlerBenannteKandidaturKonfiguration.MSG_KEY_WAEHLER_BENANNTE_LISTENKANDIDATUR_MEHRZAHL), getGebietName());
    }

    return getMessage("listenkandidatur.search.page.header", getListeName(), getGebietName());
  }

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

    super.setSearchReady();
  }

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

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

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

    return searchResultIncludingErsatzkandidaturen;
  }

  @Override
  public void resetSearchResult() {
    super.resetSearchResult();

    resetSearchResultIncludingErsatzkandidaturen();
  }

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

  @Override
  public ListenkandidaturSearchParameters getSearchParameters() {
    ListenkandidaturSearchParameters listenkandidaturSearchParameters = super.getSearchParameters();
    listenkandidaturSearchParameters.setListe(getListe());

    return listenkandidaturSearchParameters;
  }

  private void resetSearchResultIncludingErsatzkandidaturen() {
    searchResultIncludingErsatzkandidaturen = null;
  }

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

  private boolean isWaehlerBenannteListeSelected() {
    return isListeSelected() && waehlerBenannteKandidaturKonfiguration.isWaehlerBenannteListe(getListe());
  }

  private boolean isListeSelected() {
    return listeConversationSelect.isSelected();
  }

  public Liste getListe() {
    return listeConversationSelect.getEntity();
  }

  public String getListeName() {
    if (getListe() == null) {
      return null;
    }

    return getListe().getKurznameAufGebiet();
  }

  public String getGebietName() {
    if (getListe() == null) {
      return null;
    }

    return formatGebietName(getListe().getGebiet());
  }

  @Override
  public boolean isBtnResetRendered() {
    // NOTE, dass momentan alle Suchparameter 'readonly' angezeigt werden.
    return false;
  }

  @Redirect
  @Override
  public String reset() {
    setKandidaturStatusBemerkung("");

    return super.reset();
  }

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

  @Override
  @Nullable
  @Redirect
  public String goBack() {
    return defaultString(super.goBack(), PARENT_VIEW_ID);
  }

  public boolean isBtnAlleListenkandidaturenLoeschenRendered() {
    return hasPermission(UseCasePermission.LISTENKANDIDATUR_DELETE);
  }

  public boolean isBtnAlleListenkandidaturenLoeschenDisabled() {
    return isEmptySearchResultDisplayed() || !isRechtAufGebietDerListeVorhanden();
  }

  private boolean isRechtAufGebietDerListeVorhanden() {
    return isListeSelected() && isBearbeitenRechtAufGebietVorhanden(getListe().castTo(EntityMitGebiet.class).getEntity());
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.LISTENKANDIDATUR_DELETE)
  public String alleListenkandidaturenLoeschen() {
    listenkandidaturEdit.delete(getSearchResult());

    addMessageDeleteAllSuccess();

    resetSearchResult();

    return VIEW_ID;
  }

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

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

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

    formBuilder.addProperty(listeProperties.getKennwortProperty()).readonly();
    formBuilder.addProperty(listeProperties.getKurznameProperty()).readonly();

    long anzahlKandidaturenInsgesamt = 0;
    long anzahlNennungenInsgesamt = 0;
    long anzahlZugelassungsfaehigeKandidaturen = 0;
    long anzahlZugelassungsfaehigeNennungen = 0;

    long anzahlErsatzkandidaturen = 0;

    for (Kandidatur kandidatur : getSearchResultIncludingErsatzkandidaturen()) {
      anzahlKandidaturenInsgesamt++;

      if (kandidatur.isInstanceOf(Listenkandidatur.class)) {
        Listenkandidatur listenkandidatur = kandidatur.castTo(Listenkandidatur.class).getEntity();

        if (listenkandidatur.isListenkandidaturMarkiertAlsErsatzkandidatur()) {
          anzahlErsatzkandidaturen++;
        } else {
          anzahlNennungenInsgesamt += listenkandidatur.getAnzahlNennungen();

          if (getZulassungPruefer().isZulassenErlaubtUndNichtAbgelehnt(listenkandidatur)) {
            anzahlZugelassungsfaehigeKandidaturen++;
            anzahlZugelassungsfaehigeNennungen += listenkandidatur.getAnzahlNennungen();
          }
        }
      } else if (kandidatur.isInstanceOf(Ersatzkandidatur.class)) { // ELECT-6624
        anzahlErsatzkandidaturen++;

        if (getZulassungPruefer().isZulassenErlaubtUndNichtAbgelehnt(kandidatur)) {
          anzahlZugelassungsfaehigeKandidaturen++;
        }
      }
    }

    formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("listenkandidatur.search.anzahl.kandidaturen.insgesamt"), anzahlKandidaturenInsgesamt));
    formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("listenkandidatur.search.anzahl.zulassungsfaehige.kandidaturen.insgesamt"), anzahlZugelassungsfaehigeKandidaturen));

    if (isAnzahlNennungenAnzeigen()) {
      formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("listenkandidatur.search.anzahl.nennungen.insgesamt"), anzahlNennungenInsgesamt));
      formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("listenkandidatur.search.anzahl.zulassungsfaehige.nennungen.insgesamt"), anzahlZugelassungsfaehigeNennungen));
    }

    if (!isWaehlerBenannteListeSelected()) {
      formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("listenkandidatur.search.anzahl.ersatzkandidaten.insgesamt"), anzahlErsatzkandidaturen));
    }
  }

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

  private ZulassungPruefer getZulassungPruefer() {
    return zulassungPrueferRequestScope.getZulassungPruefer();
  }

  private boolean isAnzahlNennungenAnzeigen() {
    return isWahlSelected() && getSelectedWahl().isWahlMitMehrfachnennungen();
  }

  public String getKandidaturStatusBemerkung() {
    return kandidaturStatusBemerkung;
  }

  public void setKandidaturStatusBemerkung(String kandidaturStatusBemerkung) {
    this.kandidaturStatusBemerkung = kandidaturStatusBemerkung;
  }

  @Override
  public EagerLoadingCollector getEagerLoadingCollector() {
    EagerLoadingCollector collector = super.getEagerLoadingCollector();
    listenkandidaturColumnBuilder.collectEagerLoadings(collector);

    return collector;
  }
}
