
package de.ivu.elect.dokumente.ergebnis;

import de.ivu.elect.business.stimmeingabe.boundary.NlVoteType;
import de.ivu.elect.business.stimmzettel.boundary.EntityAufStimmzettelDatenDAOFactory;
import de.ivu.elect.business.stimmzettel.entity.EntityAufStimmzettelDaten;
import de.ivu.elect.business.wahl.control.AbstractNlExportArtefaktNachSystemExportstatusExportContext;
import de.ivu.elect.business.wahlvorschlag.boundary.ListeDAO;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagPK;
import de.ivu.elect.presentation.ergebnis.dokumente.gesamtergebnis.NlDefaultGesamtErgebnisDokumentKonverter;
import de.ivu.elect.was.exchange.diff.EmlErgebnisDifferenz;

public interface NlWasErgebnisdokumentMitEmlErgebnisDifferenzLeerDocumentExportMapper {

  default void initEmlErgebnisDifferenzLeer(AbstractNlExportArtefaktNachSystemExportstatusExportContext context, EntityAufStimmzettelDatenDAOFactory entityAufStimmzettelDatenDAOFactory,
      ListeDAO listeDAO) {
    boolean korrekturenStimmeingabenKopfzahlenWaehlerErfassbar = requiresKorrekturenStimmeingabenKopfzahlenWaehlerVorhanden(context);
    boolean korrekturenStimmeingabenKopfzahlenStimmzettelErfassbar = requiresKorrekturenStimmeingabenKopfzahlenStimmzettelVorhanden(context);
    boolean korrekturenStimmeingabenKopfzahlenStimmzettelAbweichendErfassbar = requiresKorrekturenStimmeingabenKopfzahlenStimmzettelAbweichendVorhanden(context);
    boolean korrekturenStimmeingabenStimmenListenIdsErfassbar = requiresKorrekturenStimmeingabenStimmenListenIds(context);

    boolean emlErgebnisDifferenzRelevant = korrekturenStimmeingabenKopfzahlenWaehlerErfassbar || korrekturenStimmeingabenKopfzahlenStimmzettelErfassbar
        || korrekturenStimmeingabenKopfzahlenStimmzettelAbweichendErfassbar || korrekturenStimmeingabenStimmenListenIdsErfassbar;

    if (emlErgebnisDifferenzRelevant) { // ELECT-16702
      EmlErgebnisDifferenz emlErgebnisDifferenz = new EmlErgebnisDifferenz();

      if (korrekturenStimmeingabenKopfzahlenWaehlerErfassbar && context.isKorrekturenStimmeingabenKopfzahlenWaehlerVorhanden()) {
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.WAEHLER_OHNE_WAHLSCHEIN, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.WAEHLER_MIT_VOLLMACHT, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.WAEHLER_GESAMT, -1L, 0L);
      }

      if (korrekturenStimmeingabenKopfzahlenStimmzettelErfassbar && context.isKorrekturenStimmeingabenKopfzahlenStimmzettelVorhanden()) {
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.GUELTIGE_INSGESAMT, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.BLANCO, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.UNGUELTIGE, -1L, 0L);
      }

      if (korrekturenStimmeingabenKopfzahlenStimmzettelAbweichendErfassbar && context.isKorrekturenStimmeingabenKopfzahlenStimmzettelAbweichendVorhanden()) {
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.STIMMZETTEL_EINGENOMMEN_ZU_VIEL, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.STIMMZETTEL_EINGENOMMEN_ZU_WENIG, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.STIMMZETTEL_ZU_VIEL_AUSGEGEBEN, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.STIMMZETTEL_ZU_WENIG_AUSGEGEBEN, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.STIMMZETTEL_NICHT_ABGEGEBEN, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.STIMMZETTEL_ABWEICHEND_ANDERER_GRUND, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.STIMMZETTEL_ABWEICHEND_UNBEKANNTER_GRUND, -1L, 0L);

        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.BRIEFWAHL_STIMMZETTEL_EINGENOMMEN_ZU_VIEL, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.BRIEFWAHL_STIMMZETTEL_EINGENOMMEN_ZU_WENIG, -1L, 0L);
        emlErgebnisDifferenz.addVoteTypeUnterschied(NlVoteType.BRIEFWAHL_STIMMZETTEL_VERLOREN, -1L, 0L);
      }

      if (korrekturenStimmeingabenStimmenListenIdsErfassbar && !context.getKorrekturenStimmeingabenStimmenListenIds().isEmpty()) {
        EntityAufStimmzettelDaten entityAufStimmzettelDaten = entityAufStimmzettelDatenDAOFactory.getEntityAufStimmzettelDaten();

        context.getKorrekturenStimmeingabenStimmenListenIds().forEach(listeId -> {
          Liste liste = listeDAO.findByPrimaryKey(new WahlvorschlagPK(listeId));
          Long listeStimmzettelPosition = liste.getStimmzettelPosition(entityAufStimmzettelDaten).getPosition();

          if (listeStimmzettelPosition != null) {
            String affiliationIdentifier = "" + listeStimmzettelPosition;

            emlErgebnisDifferenz.addListenstimmenUnterschied(affiliationIdentifier, -1L, 0L);

            liste.getListenkandidaturen().forEach(listenkandidatur -> {
              Long listenkandidaturStimmzettelPosition = listenkandidatur.getStimmzettelPosition(entityAufStimmzettelDaten).getPosition();

              if (listenkandidaturStimmzettelPosition != null) {
                String candidateIdentifier = "" + listenkandidaturStimmzettelPosition;

                emlErgebnisDifferenz.addListenkandidaturstimmenUnterschied(affiliationIdentifier, candidateIdentifier, -1L, 0L);
              }
            });
          }
        });
      }

      context.put(NlDefaultGesamtErgebnisDokumentKonverter.EML_ERGEBNIS_DIFFERENZ_KEY, emlErgebnisDifferenz);
    }
  }

  boolean requiresKorrekturenStimmeingabenKopfzahlenWaehlerVorhanden(AbstractNlExportArtefaktNachSystemExportstatusExportContext context);

  boolean requiresKorrekturenStimmeingabenKopfzahlenStimmzettelVorhanden(AbstractNlExportArtefaktNachSystemExportstatusExportContext context);

  boolean requiresKorrekturenStimmeingabenKopfzahlenStimmzettelAbweichendVorhanden(AbstractNlExportArtefaktNachSystemExportstatusExportContext context);

  boolean requiresKorrekturenStimmeingabenStimmenListenIds(AbstractNlExportArtefaktNachSystemExportstatusExportContext context);
}
