package de.ivu.elect.presentation.wahl;

import java.util.List;
import java.util.stream.Collectors;

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

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.CurrentCustomer;
import de.ivu.elect.business.ergebnis.boundary.ErgebnisSessionSelect;
import de.ivu.elect.business.ergebnis.entity.Ergebnis;
import de.ivu.elect.business.ergebniskonflikt.boundary.ErgebnisKonfliktDAO;
import de.ivu.elect.business.ergebniskonflikt.entity.ErgebnisKonflikt;
import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.boundary.WahldurchfuehrungsgebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.control.EntityMitWurzelgebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.AbstractGebiet;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.NlGebietCustomData;
import de.ivu.elect.business.stimmeingabe.boundary.LetzterEingangLoader;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingangsart;
import de.ivu.elect.business.wahl.entity.NlWahlCustomData;
import de.ivu.elect.business.wahl.entity.NlWahlPhase;
import de.ivu.elect.business.wahl.entity.NlWahlart;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.business.wahlvorschlag.boundary.WahlvorschlagExtendedDAO;
import de.ivu.elect.jee.faces.UserLocale;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.LambdaBooleanProperty;
import de.ivu.elect.jee.presentation.dynamicform.ReadOnlyLongProperty;
import de.ivu.elect.jee.presentation.dynamicform.ReadOnlyStringProperty;
import de.ivu.elect.presentation.security.NlPrivatePublicKeyNeeded;

@Specializes
public class NlWasWahlprozessView extends NlWahlprozessView {
  private static final long serialVersionUID = 1L;

  @Inject
  private transient WahlvorschlagExtendedDAO wahlvorschlagExtendedDAO;
  @Inject
  private transient UserLocale userLocale;

  @Inject
  private transient GebietExtendedDAO gebietExtendedDAO;

  @Inject
  private transient ErgebnisSessionSelect ergebnisSessionSelect;

  @Inject
  private transient ErgebnisKonfliktDAO konfliktDAO;

  @Inject
  private transient CurrentCustomer currentCustomer;

  @Inject
  private transient WahldurchfuehrungsgebietExtendedDAO wahldurchfuehrungsgebietExtendedDAO;

  @Inject
  private transient NlPrivatePublicKeyNeeded nlPrivatePublicKeyNeeded;

  @Inject
  private transient LetzterEingangLoader letzterEingangLoader;

  @Override
  protected void addProperties(FormBuilder formBuilder) {
    super.addProperties(formBuilder);

    Wahl selectedWahl = getSelectedWahl();
    if (selectedWahl == null) {
      formBuilder.addSeparator("nl.was.wahlprozess.keine.wahl.separator");
      return;
    }

    NlWahlPhase nlWahlPhase = selectedWahl.getCustomData(NlWahlCustomData.class).getNlWahlPhase();
    List<Gebiet> erfassungsgebiete = gebietExtendedDAO.findByWahl(selectedWahl).stream().filter(AbstractGebiet::isErfassungsgebiet)
        .collect(Collectors.toList());
    long anzahlErfassungsgebiete = erfassungsgebiete.size();
    if (nlWahlPhase.isInitial()) {
      formBuilder.addSeparator("nl.was.wahlprozess.initial.separator");
      int anzahlWahlvorschlaege = wahlvorschlagExtendedDAO.findByWahl(selectedWahl).size();
      formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("nl.was.wahlprozess.wahlvorschlaege"),
          (long) anzahlWahlvorschlaege));
      formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("nl.was.wahlprozess.erfassungsgebiete"), anzahlErfassungsgebiete));
      if (anzahlErfassungsgebiete == 0 || anzahlWahlvorschlaege == 0) {
        addError(formBuilder, "NlWahlPhase.ERFASSUNG.button.disabled.grund");
      }

    }

    // ELECTVAPP-1150 ELECTVAPP-1144
    if ((nlWahlPhase.isInitial()  || nlWahlPhase.isErfassung()) && anzahlErfassungsgebiete > 0 && nlPrivatePublicKeyNeeded.isPublicKeyNeeded(getMandant())) {
      formBuilder.addSeparator("nl.was.wahlprozess.public.key");

      long anzahlMitSchluessel = erfassungsgebiete.stream().filter(g -> g.getCustomData(NlGebietCustomData.class).isPublicKeyValid()).count();
      long anzahlOhneSchluessel = anzahlErfassungsgebiete - anzahlMitSchluessel;

      formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("nl.was.wahlprozess.erfassungsgebiete.ohne.public.key"), anzahlOhneSchluessel));
      if (anzahlOhneSchluessel>0) {
        addWarning(formBuilder, "NlWahlPhase.ERFASSUNG.erfassungsgebiete.ohne.public.key");
      }

    }


    long anzahlErfassungsgebieteMitUngueltigenEingaenge = getAnzahlErfassungsgebieteMitUngueltigenEingaenge();
    if (nlWahlPhase.isErfassung() && anzahlErfassungsgebieteMitUngueltigenEingaenge != 0) {
      formBuilder.addSeparator("nl.was.wahlprozess.erfassung.separator");
      formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("nl.was.wahlprozess.erfassungsgebiete.ungueltig"),
              anzahlErfassungsgebieteMitUngueltigenEingaenge));
      addError(formBuilder, "NlWahlPhase.ABSCHLUSS.button.disabled.grund");
    }





    if (nlWahlPhase.isErgebnisAnzeigen()) {
      Ergebnis entity = ergebnisSessionSelect.getEntity();
      if (entity != null) {
        List<ErgebnisKonflikt> konflikte = konfliktDAO.findByErgebnisOrderById(entity);
        if (!konflikte.isEmpty()) {
          formBuilder.addSeparator("nl.was.wahlprozess.losen.separator");
          formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("nl.was.wahlprozess.losen.gesamtzahl"), (long) konflikte.size()));
          long anzahlOffenerLosentscheide = konflikte.stream()
                  .filter(ergebnisKonflikt -> !ergebnisKonflikt.isGeloest()).count();
          formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("nl.was.wahlprozess.losen.offene.lose"), anzahlOffenerLosentscheide));
          if (anzahlOffenerLosentscheide > 0) {
            addError(formBuilder, "nl.was.wahlprozess.offene.losentscheid.vorhanden.error");
          }
        }
      }
    }

    // warum nicht immer...if(nlWahlPhase.isErfassung()){
    formBuilder.addSeparator("nl.was.wahlprozess.wahl.info.separator");
    formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("nl.was.wahlprozess.wahlart"),
            selectedWahl.getWahlart().getTitel()));
   formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("nl.was.wahlprozess.datum"),
            userLocale.formatDate(selectedWahl.getWahldatum())));//ELECTVAPP-303
    NlWahlCustomData nlWahlCustomData = selectedWahl.getCustomData(NlWahlCustomData.class);//ELECTVAPP-640

    if(NlWahlart.isWasPSB(selectedWahl, currentCustomer.getCustomer())) {

      if (nlWahlCustomData.isZentraleErfassung()) {
        formBuilder.addProperty(new LambdaBooleanProperty(getMessage("entity.einzahl.WAHL.ZENTRALE_ERFASSUNG"), false, nlWahlCustomData::setZentraleErfassung,
            nlWahlCustomData::isZentraleErfassung)).readonly();
      } else {
        // ELECTVAPP-1025
        formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("entity.einzahl.WAHL.ZENTRALE_ERFASSUNG"), getMessage("entity.einzahl.WAHL.ZENTRALE_ERFASSUNG.false")));
      }

    //ELECTVAPP-916
    }
    Gebiet wurzelgebiet = selectedWahl.getWurzelgebiet(EntityMitWurzelgebietDAO.fromDao(gebietExtendedDAO));
    if (wurzelgebiet != null && /*ELECTVAPP-771*/NlWahlart.isWasCSB(selectedWahl, currentCustomer.getCustomer())) {
      formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("nl.was.wahlprozess.sitze"), wurzelgebiet.getAnzahlSitze()));
    }

    if (NlWahlart.isWasCSB(selectedWahl, currentCustomer.getCustomer())) {
      if (selectedWahl.getQuorumProzenthuerde() != null) {
        // ELECTVAPP-771
        formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("nl.was.wahlprozess.vorrangschwelle"),
            selectedWahl.getQuorumProzenthuerde().longValue()));
      }
    }


    formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("nl.was.wahlprozess.dateiname.wahl"),
            nlWahlCustomData.getEml110Filename()));//ELECT-10358
    formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("nl.was.wahlprozess.datum.wahl"),
            userLocale.formatDateTime(nlWahlCustomData.getEml110Date())));//ELECT-10358
    if (StringUtils.isNotBlank(nlWahlCustomData.getEml110HashCode())) {
      formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("nl.was.wahlprozess.hashcode.wahl"),
              nlWahlCustomData.getEml110HashCode()));//ELECT-10358
    }


    // ELECTVAPP-1034
    if (NlWahlart.isWasCSB(selectedWahl, currentCustomer.getCustomer())){
      formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("nl.was.wahlprozess.dateiname.kandidaten.csb"), nlWahlCustomData.getEml230Filename()));
      //ELECT-10358
    } else {
      formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("nl.was.wahlprozess.dateiname.kandidaten"), nlWahlCustomData.getEml230Filename()));//ELECT-10358
    }


    formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("nl.was.wahlprozess.datum.kandidaten"),
            userLocale.formatDateTime(nlWahlCustomData.getEml230Date())));//ELECT-10358
    if (StringUtils.isNotBlank(nlWahlCustomData.getEml230HashCode())) {
      formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("nl.was.wahlprozess.hashcode.kandidaten"),
              nlWahlCustomData.getEml230HashCode()));//ELECT-10358
    }

    // warum nicht immer... }

  }




  private long getAnzahlErfassungsgebieteMitUngueltigenEingaenge() {
    Wahl selectedWahl = getSelectedWahl();
    Ergebniseingangsart ergebniseingangsart = selectedWahl.castTo(Wahldurchfuehrung.class).getEntity().getErgebniseingangsart();
    return wahldurchfuehrungsgebietExtendedDAO.findByWahl(selectedWahl).stream().filter(
        wahldurchfuehrungsgebiet -> wahldurchfuehrungsgebiet.isErfassungsgebiet() && (!letzterEingangLoader
            .bestimmeLetztenEingang(wahldurchfuehrungsgebiet.getWahl().getPk(), wahldurchfuehrungsgebiet.getPk()
                , ergebniseingangsart).isInErgebnisUebernehmbar())).count();
  }
}
