
package de.ivu.elect.presentation.wahlvorschlag.action;

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

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

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.gebietsbaum.boundary.GebietSessionSelect;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturEdit;
import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturExtendedDAO;
import de.ivu.elect.business.pruefung.boundary.ZulassungPruefer;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.wahl.entity.NlWahlart;
import de.ivu.elect.business.wahlrechtspruefung.boundary.WahlrechtspruefungExtendedDAO;
import de.ivu.elect.business.wahlrechtspruefung.entity.NlPruefkriteriumAuswirkung;
import de.ivu.elect.business.wahlrechtspruefung.entity.NlWahlrechtspruefung;
import de.ivu.elect.business.wahlrechtspruefung.entity.Wahlrechtspruefung;
import de.ivu.elect.business.wahlvorschlag.boundary.ListeConversationSelect;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.NlListe;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagStatus;
import de.ivu.elect.jee.faces.FacesContextUtil;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.wahl.CurrentWahlZulassungspruefungExtended;
import de.ivu.elect.presentation.wahlvorschlag.NlListeActionHelper;
import de.ivu.elect.presentation.wahlvorschlag.NlListeSearchView;


import static java.util.stream.Collectors.joining;

@Named(NlListeZulassungAblehnenMitBemerkungAction.COMPONENT_NAME)
// ELECT-10224, cf. NlListenkandidaturZulassungAblehnenMitBemerkungAction!
public class NlListeZulassungAblehnenMitBemerkungAction extends AbstractListeZulassungAction {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "nlListeZulassungAblehnenMitBemerkungAction";

  public static final String DIALOG_TEMPLATE_PATH = "/WEB-INF/templates/wahlvorschlag/liste-zulassung-ablehnen-mit-bemerkung-dialog.xhtml";

  @Inject
  private transient GebietSessionSelect gebietSessionSelect;

  @View
  @Inject
  private transient NlListeSearchView nlListeSearchView;

  @Inject
  private transient ListeConversationSelect listeConversationSelect;

  @Inject
  private transient NlListeActionHelper nlListeActionHelper;

  @Inject
  private transient ListeZulassungAblehnenAction listeZulassungAblehnenAction;

  @Inject
  private transient WahlrechtspruefungExtendedDAO wahlrechtspruefungExtendedDAO;

  @Inject
  private transient ListenkandidaturEdit listenkandidaturEdit;

  @Inject
  private transient ListenkandidaturExtendedDAO listenkandidaturExtendedDAO;

  public NlListeZulassungAblehnenMitBemerkungAction() {
    super();
  }

  @Override
  protected UseCasePermission getRequiredPermission() {
    return listeZulassungAblehnenAction.getRequiredPermission();
  }

  @Override
  public boolean isDisabledInternal(Liste liste, CurrentWahlZulassungspruefungExtended currentWahlZulassungspruefung) {
    liste.setListenkandidaturenPreloader(listenkandidaturExtendedDAO);

    return listeZulassungAblehnenAction.isDisabledInternal(liste, currentWahlZulassungspruefung);
  }

  @Override
  protected WahlvorschlagStatus getWahlvorschlagStatus() {
    return listeZulassungAblehnenAction.getWahlvorschlagStatus();
  }

  public String getWahlvorschlagStatusBemerkung() {
    return nlListeSearchView.getWahlvorschlagStatusBemerkung();
  }

  public void setWahlvorschlagStatusBemerkung(String wahlvorschlagStatusBemerkung) {
    nlListeSearchView.setWahlvorschlagStatusBemerkung(wahlvorschlagStatusBemerkung);
  }

  @Override
  @Nullable
  protected String doIt(Liste template) {
    listeConversationSelect.setEntity(template);

    Liste liste = listeConversationSelect.getEntity();

    // ELECT-10750
    String wahlvorschlagStatusBemerkung = NlListe.formatPruefungenZuBehebenLangtexteExcludingZulassungPrueferExtraInformation(getZulassungPruefer(), liste).stream() //
        .filter(StringUtils::isNotBlank) //
        .collect(joining(NlListe.ZULASSUNG_ABGELEHNT_BEGRUENDUNG_SEPARATOR));

    setWahlvorschlagStatusBemerkung(wahlvorschlagStatusBemerkung);

    return null; // Return to current page and display the dialog!
  }

  @Override
  public String getDialogName() {
    return "NlListeZulassungAblehnenMitBemerkungConfirm";
  }

  public String getDialogHeader() {
    return getLocalizedLabel();
  }

  public String getDialogMessage() {
    return getMessage("liste.search.action.nicht.zulassen.mit.bemerkung.confirm.message");
  }

  public void doActionConfirmedListe() {
    doActionConfirmed(NlPruefkriteriumAuswirkung.LISTE);
  }

  public boolean isConfirmRenderedListe() {
    return nlListeActionHelper.isButtonConfirmedWahlkreisRendered(getListe(), getSelectedGebiet());
  }

  public String getLabelConfirmedListe() {
    if (isWahlMitWahlkreisen()) {
      return getMessage("nl.liste.nicht.zulassen.wahlkreis");
    }

    return getMessage("nl.liste.nicht.zulassen.liste");
  }

  public void doActionConfirmedStel() {
    doActionConfirmed(NlPruefkriteriumAuswirkung.STEL);
  }

  public boolean isConfirmRenderedStel() {
    return nlListeActionHelper.isButtonConfirmedStelRendered(getListe(), getSelectedGebiet());
  }

  public String getLabelConfirmedStel() {
    return getMessage("nl.liste.nicht.zulassen.stel");
  }

  public void doActionConfirmedGruppe() {
    doActionConfirmed(NlPruefkriteriumAuswirkung.GRUPPE);
  }

  public boolean isConfirmRenderedGruppe() {
    return nlListeActionHelper.isButtonConfirmedGruppeRendered(getListe(), getSelectedGebiet());
  }

  public String getLabelConfirmedGruppe() {
    return getMessage("nl.liste.nicht.zulassen.gruppe");
  }

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

  // NOTE, dass diese Methode in /nl-core-jar/src/main/resources/META-INF/contracts/custom/WEB-INF/templates/wahlvorschlag/liste-zulassung-ablehnen-mit-bemerkung-dialog.xhtml aufgerufen wird!
  public void doActionConfirmed(NlPruefkriteriumAuswirkung nlPruefkriteriumAuswirkung) {
    Liste liste = listeConversationSelect.getEntity();
    liste.getTransientContext().put(NlPruefkriteriumAuswirkung.AUSWIRKUNG_CONTEXT_KEY, nlPruefkriteriumAuswirkung);
    liste.getTransientContext().put(NlPruefkriteriumAuswirkung.BEMERKUNG_AFTER_ACTION_KEY, getWahlvorschlagStatusBemerkung());

    String outcome = doActionConfirmed(liste);

    listeConversationSelect.clearEntity();

    refreshViewOnNonBlankResult(liste, outcome);
  }

  private String doActionConfirmed(Liste liste) {
    if (liste != null && isActionPossible(liste)) {
      String wahlvorschlagStatusBemerkung = getWahlvorschlagStatusBemerkung();

      String outcome = listeZulassungAblehnenAction.doIt(liste, getWahlvorschlagStatus(), wahlvorschlagStatusBemerkung);

      NlListe.setZulassungAbgelehntBegruendung(liste, wahlvorschlagStatusBemerkung);

      // ELECT-10834 aber ELECTVAPP-1697
      // lehneOffeneKandidaturenAb(liste, wahlvorschlagStatusBemerkung);

      return outcome;
    }

    return FacesContextUtil.getCurrentViewId();
  }

  private List<String> getVersaeumnistexteFuerKandidatur(List<Wahlrechtspruefung> byKandidatur) {
    List<String> versaeumnisse = new ArrayList<>();

    byKandidatur.stream().filter(wahlrechtspruefung -> wahlrechtspruefung.getWahlrechtspruefStatus().isNichtErfuellt()).forEach(wahlrechtspruefung -> {
      NlWahlrechtspruefung nlWahlrechtspruefung = NlWahlrechtspruefung.from(wahlrechtspruefung);
      String bemerkung = wahlrechtspruefung.getBemerkung();

      if (bemerkung == null) {
        versaeumnisse.add(nlWahlrechtspruefung.formatText(nlWahlrechtspruefung.getPruefkriterium().getTextFuerProtokollNichtErfuellt()));
      } else {
        versaeumnisse.add(bemerkung);
      }
    });

    return versaeumnisse;
  }

  @Override
  public String getLabelKey() {
    return listeZulassungAblehnenAction.getLabelKey();
  }

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

  private boolean isWahlMitWahlkreisen() {
    Gebiet gebiet = getSelectedGebiet();

    if (gebiet != null) {
      return NlWahlart.valueOf(gebiet.getWahl()).isWahlartMitWahlkreisen();
    }

    return true; // Bisheriger Standard...
  }

  private Gebiet getSelectedGebiet() {
    return gebietSessionSelect.getEntity();
  }
}
