package de.ivu.elect.presentation;

import javax.enterprise.inject.Specializes;
import javax.inject.Inject;

import de.ivu.elect.business.ergebnis.boundary.ErgebnisSessionSelect;
import de.ivu.elect.business.ergebnis.entity.Ergebnis;
import de.ivu.elect.business.ergebniskonflikt.boundary.ErgebnisKonfliktExtendedDAO;
import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.entity.NlGebiet;
import de.ivu.elect.business.gebietsbaum.entity.NlGebietCustomData;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.wahl.boundary.WahlExtendedDAO;
import de.ivu.elect.business.wahl.entity.NlWahlCustomData;
import de.ivu.elect.business.wahl.entity.NlWahlPhase;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.presentation.ergebniskonflikt.menu.ErgebnisKonfliktSearchMenuItemEntry;
import de.ivu.elect.presentation.gebietsbaum.menu.GebietSearchMenuItemEntry;
import de.ivu.elect.presentation.gebietsbaum.menu.GebietStimmbezirkImportMenuItemEntry;
import de.ivu.elect.presentation.gebietsbaum.menu.VoteValueEditMenuItemEntry;
import de.ivu.elect.presentation.mandant.MandantSessionSelect;
import de.ivu.elect.presentation.security.NlPrivatePublicKeyNeeded;
import de.ivu.elect.presentation.security.menu.NlPublicKeyEditMenuItem;
import de.ivu.elect.presentation.stimmeingabe.menu.StimmeingabeErfassenMenuItemEntry;
import de.ivu.elect.presentation.wahl.menu.NlWahlprozessMenuItemEntry;
import de.ivu.elect.presentation.wahl.menu.WahlImportMenuItemEntry;
import de.ivu.elect.presentation.wahlvorschlag.menu.WahlvorschlagImportMenuItemEntry;

@Specializes
public class NlWasStartViewResolver extends WasStartViewResolver {
  private static final long serialVersionUID = 1L;

  @Inject
  private transient WahlImportMenuItemEntry wahlImportMenuItemEntry;

  @Inject
  private transient WahlvorschlagImportMenuItemEntry wahlvorschlagImportMenuItemEntry;

  @Inject
  private transient VoteValueEditMenuItemEntry voteValueEditMenuItemEntry;

  @Inject
  private transient GebietStimmbezirkImportMenuItemEntry gebietStimmbezirkImportMenuItemEntry;

  @Inject
  private transient StimmeingabeErfassenMenuItemEntry stimmeingabeErfassenMenuItemEntry;

  @Inject
  private transient NlWahlprozessMenuItemEntry nlWahlprozessMenuItemEntry;

  @Inject
  private transient ErgebnisSessionSelect ergebnisSessionSelect;

  @Inject
  protected transient ErgebnisKonfliktSearchMenuItemEntry ergebnisKonfliktSearchMenuItemEntry;

  @Inject
  private transient ErgebnisKonfliktExtendedDAO ergebnisKonfliktExtendedDAO;

  @Inject
  private transient NlPublicKeyEditMenuItem nlPublicKeyEditMenuItem;

  @Inject
  private transient GebietSearchMenuItemEntry gebietSearchMenuItemEntry;

  @Inject
  private transient NlPrivatePublicKeyNeeded nlPrivatePublicKeyNeeded;

  @Inject
  private transient GebietExtendedDAO gebietExtendedDAO;

  @Inject
  private transient MandantSessionSelect mandantSessionSelect;

  @Inject
  private transient WahlExtendedDAO wahlExtendedDAO;

  @Override
  protected String getWasStartViewId() {
    // ELECT-9793
    if (wahlImportMenuItemEntry.isPossible() && !isWahlenVorhanden() /*ELECT-13397*/) {
      return wahlImportMenuItemEntry.getTargetViewId();
    }

    // ELECT-9812 Wahlvorschläge vor Stimmbezirken
    if (wahlvorschlagImportMenuItemEntry.isPossible()) {
      return wahlvorschlagImportMenuItemEntry.getTargetViewId();
    }

    // ELECTVAPP-1143
    if (nlPublicKeyEditMenuItem.isPossible() && !isPublicExported()) {
      return nlPublicKeyEditMenuItem.getTargetViewId();
    }

    if (voteValueEditMenuItemEntry.isPossible() && !isVoteValuesPresent()) {
      return voteValueEditMenuItemEntry.getTargetViewId();
    }

    if (gebietSearchMenuItemEntry.isPossible() && isPublicKeyImportRechtVorhanden() && isPublicKeyImportNeeded() && isErfassungsGebietOhnePublicKeyVorhanden()) {
      return gebietSearchMenuItemEntry.getTargetViewId(); // ELECT-11660
    }

    if (gebietStimmbezirkImportMenuItemEntry.isPossible()) {
      return gebietStimmbezirkImportMenuItemEntry.getTargetViewId();
    }

    if (getNlWahlPhase().isErfassung()) {
      if (stimmeingabeErfassenMenuItemEntry.isPossible()) {
        return stimmeingabeErfassenMenuItemEntry.getTargetViewId();
      }
    }

    if (getNlWahlPhase().isSitzberechnung() && ergebnisKonfliktSearchMenuItemEntry.isPossible() && isOffeneLoseVorhanden()) {
      return ergebnisKonfliktSearchMenuItemEntry.getTargetViewId();
    }

    if (nlWahlprozessMenuItemEntry.isPossible()) {
      return nlWahlprozessMenuItemEntry.getTargetViewId();
    }

    if (stimmeingabeErfassenMenuItemEntry.isPossible()) {
      return stimmeingabeErfassenMenuItemEntry.getTargetViewId();
    }

    return super.getWasStartViewId();
  }

  private boolean isVoteValuesPresent() {
    Wahl wahl = getSelectedWahl();

    return wahl != null && NlGebiet.collectVoteValueGebiete(wahl, gebietExtendedDAO).stream().allMatch(gebiet -> gebiet.getCustomData(NlGebietCustomData.class).getVoteValue() != null);
  }

  private boolean isWahlenVorhanden() {
    Mandant mandant = mandantSessionSelect.getMandant();
    if (mandant == null) {
      return false;
    }
    return !wahlExtendedDAO.findByAll(mandant).isEmpty();
  }

  public boolean isPublicKeyImportNeeded() {
    Wahl selectedWahl = getSelectedWahl();
    return selectedWahl != null && nlPrivatePublicKeyNeeded.isPublicKeyNeeded(selectedWahl.getMandant());
  }

  private boolean isErfassungsGebietOhnePublicKeyVorhanden() {
    Wahl selectedWahl = getSelectedWahl();
    return selectedWahl != null && gebietExtendedDAO.findByWahl(selectedWahl).stream()
        .anyMatch(gebiet -> gebiet.isErfassungsgebiet() && !gebiet.getCustomData(NlGebietCustomData.class).isPublicKeyPresent());
  }

  public boolean isPublicKeyImportRechtVorhanden() {
    return hasPermission(UseCasePermission.CUSTOMER_1);
  }

  private boolean isPublicExported() {
    Wahl selectedWahl = getSelectedWahl();
    return selectedWahl != null && selectedWahl.getCustomData(NlWahlCustomData.class).isPublicKeyExported();
  }

  private NlWahlPhase getNlWahlPhase() {
    Wahl selectedWahl = getSelectedWahl();
    if (selectedWahl == null) {
      return NlWahlPhase.NICHT_GESETZT;
    }

    return selectedWahl.getCustomData(NlWahlCustomData.class).getNlWahlPhase();
  }

  protected boolean isOffeneLoseVorhanden() {
    Ergebnis ergebnis = ergebnisSessionSelect.getEntity();
    if (ergebnis == null) {
      return false;
    }

    return ergebnisKonfliktExtendedDAO.findByErgebnisOrderById(ergebnis).stream()
        .anyMatch(ergebnisKonflikt -> !ergebnisKonflikt.isGeloest());
  }

}
