
package de.ivu.elect.business.ergebnis.control;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.aufgabe.entity.Aufgabe;
import de.ivu.elect.business.ergebnis.entity.DHondtQuotient;
import de.ivu.elect.business.ergebnis.entity.Ergebnis;
import de.ivu.elect.business.ergebnis.entity.ErgebnisLogEintrag;
import de.ivu.elect.business.ergebnis.entity.Gewaehlt;
import de.ivu.elect.business.ergebnis.entity.Sitze;
import de.ivu.elect.business.ergebniskonflikt.entity.ErgebnisKonflikt;
import de.ivu.elect.business.fremdkandidatur.entity.Fremdkandidatur;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietPolygonPoint;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsgruppierung;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.SystemGruppeEigenschaften;
import de.ivu.elect.business.gruppeimgebiet.control.GruppeImGebietReihenfolgeVorsortierer;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.internet.entity.InternetSeite;
import de.ivu.elect.business.kandidatenportal.entity.WvpWarnung;
import de.ivu.elect.business.kandidatur.control.StimmzettelFormatter;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.niederschrift.entity.Niederschrift;
import de.ivu.elect.business.person.entity.PersonenVerknuepfung;
import de.ivu.elect.business.personenpruefung.entity.PersonPruefungKonfiguration;
import de.ivu.elect.business.pruefung.boundary.ZulassungPruefer;
import de.ivu.elect.business.staat.entity.StaatenGruppe;
import de.ivu.elect.business.stimmeingabe.boundary.StimmeingabeErfassenDescriptionResolver;
import de.ivu.elect.business.stimmeingabe.entity.ErgebnisGueltigerEingang;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingangsart;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiKonfiguration;
import de.ivu.elect.business.stimmen.control.ErgebnisStimmenFilter;
import de.ivu.elect.business.stimmzettel.boundary.EntityAufStimmzettelDatenStimmzettelPositionBerechnung;
import de.ivu.elect.business.stimmzettel.entity.Stimmzettel;
import de.ivu.elect.business.stimmzettel.entity.StimmzettelKopfdatum;
import de.ivu.elect.business.veranstaltung.entity.Veranstaltung;
import de.ivu.elect.business.wahl.control.GewaehlteLoader;
import de.ivu.elect.business.wahl.control.Loader;
import de.ivu.elect.business.wahl.control.ParameterLoader;
import de.ivu.elect.business.wahl.control.SitzeLoader;
import de.ivu.elect.business.wahl.control.StimmenLoader;
import de.ivu.elect.business.wahl.entity.AbstractWahlParameterLoader;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.business.wahlausschuss.entity.WahlausschussEntschaedigung;
import de.ivu.elect.business.wahlausschuss.entity.Wahlausschussmitglied;
import de.ivu.elect.business.wahlbeteiligung.entity.WahlbeteiligungAuswertung;
import de.ivu.elect.business.wahlbeteiligung.entity.WahlbeteiligungVerlauf;
import de.ivu.elect.business.wahlrechtspruefung.entity.Pruefkriterium;
import de.ivu.elect.business.wahlrechtspruefung.entity.Wahlrechtspruefung;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.business.wahlvorschlagsperson.entity.WahlvorschlagsPerson;

public class ErgebnisDatenLoader extends StimmergebnisDaten {

  private static final long serialVersionUID = 1L;

  private static final Logger LOG = LoggerFactory.getLogger(ErgebnisDatenLoader.class);

  private final Loader<ErgebnisKonflikt> konflikteLoader;

  private final Loader<ErgebnisLogEintrag> ergebnisLogeintraegeLoader;

  private final Loader<DHondtQuotient> dHondtQuotientenLoader;

  private final Loader<ErgebnisGueltigerEingang> gueltigerEingaengeLoader;

  private List<ErgebnisKonflikt> konflikte;

  private List<ErgebnisLogEintrag> ergebnisLogeintraege;

  private List<DHondtQuotient> dHondtQuotienten;

  private List<ErgebnisGueltigerEingang> gueltigerEingaenge;

  public ErgebnisDatenLoader(StimmergebnisDaten stimmergebnisDaten, Loader<ErgebnisKonflikt> konflikteLoader,
                             Loader<ErgebnisLogEintrag> ergebnisLogeintraegeLoader, Loader<DHondtQuotient> dHondtQuotientenLoader, Loader<ErgebnisGueltigerEingang> gueltigerEingaengeLoader) {
    super(stimmergebnisDaten);

    this.konflikteLoader = konflikteLoader;
    this.ergebnisLogeintraegeLoader = ergebnisLogeintraegeLoader;
    this.dHondtQuotientenLoader = dHondtQuotientenLoader;
    this.gueltigerEingaengeLoader = gueltigerEingaengeLoader;
  }

  public ErgebnisDatenLoader(ErgebnisDatenLoader ergebnisDatenLoader) {
    this(ergebnisDatenLoader.getWahl(),
        ergebnisDatenLoader.getGebieteLoader(),
        ergebnisDatenLoader.getGruppenLoader(),
        ergebnisDatenLoader.getGruppenImGebietLoader(),
        ergebnisDatenLoader.getWahlvorschlaegeLoader(),
        ergebnisDatenLoader.getKandidaturenLoader(),
        ergebnisDatenLoader.getPersonenVerknuepfungenLoader(),
        ergebnisDatenLoader.getStimmenLoader(),
        ergebnisDatenLoader.getGewaehlteLoader(),
        ergebnisDatenLoader.getSitzeLoader(),
        ergebnisDatenLoader.getStaatenGruppenLoader(),
        ergebnisDatenLoader.getGebietsgruppierungenLoader(),
        ergebnisDatenLoader.getWahlvorschlagsPersonenLoader(),
        ergebnisDatenLoader.getWahlausschussmitgliederLoader(),
        ergebnisDatenLoader.getWahlausschussEntschaedigungenLoader(),
        ergebnisDatenLoader.getErgebnis(),
        ergebnisDatenLoader.getErgebnisVorperiode(),
        ergebnisDatenLoader.getStimmen(),
        ergebnisDatenLoader.getSystemGruppeEigenschaften(),
        ergebnisDatenLoader.getStimmenKumulierer(),
        ergebnisDatenLoader.getWahlParameterLoader(),
        ergebnisDatenLoader.getZulassungPruefer(),
        ergebnisDatenLoader.getStimmzettelFormatter(),
        ergebnisDatenLoader.getEntityAufStimmzettelDatenStimmzettelPositionBerechnung(),
        ergebnisDatenLoader.getGruppeImGebietReihenfolgeVorsortierer(),
        ergebnisDatenLoader.getGebietPolygonPointsLoader(),
        ergebnisDatenLoader.getFremdkandidaturenLoader(),
        ergebnisDatenLoader.getInternetSeitenLoader(),
        ergebnisDatenLoader.getKonflikteLoader(),
        ergebnisDatenLoader.getErgebnisLogeintraegeLoader(),
        ergebnisDatenLoader.getdHondtQuotientenLoader(),
        ergebnisDatenLoader.getGueltigerEingaengeLoader(),
        ergebnisDatenLoader.getErfassteGebieteLoader(),
        ergebnisDatenLoader.getErgebnisStimmenFilter(),
        ergebnisDatenLoader.getLetzterErgebniseingangLoader(),
        ergebnisDatenLoader.getErgebnisGueltigerEingangLoader(),
        ergebnisDatenLoader.getWahlbeteiligungVerlaeufeLoader(),
        ergebnisDatenLoader.getWahlbeteiligungAuswertungenLoader(),
        ergebnisDatenLoader.getStimmeingabeErfassenDescriptionResolver(),
        ergebnisDatenLoader.getStimmeingabePlausiKonfigurationenLoader(),
        ergebnisDatenLoader.getVeranstaltungenLoader(),
        ergebnisDatenLoader.getStimmzettelLoader(),
        ergebnisDatenLoader.getStimmzettelKopfdatenLoader(),
        ergebnisDatenLoader.getPruefkriterienLoader(),
        ergebnisDatenLoader.getWahlrechtspruefungenLoader(),
        ergebnisDatenLoader.getWvpWarnungenLoader(),
        ergebnisDatenLoader.getPersonPruefungKonfigurationLoader(),
        ergebnisDatenLoader.getNiederschriftLoader(),
        ergebnisDatenLoader.getAufgabenLoader());
  }

  public ErgebnisDatenLoader(Wahldurchfuehrung wahl,
                             Loader<Wahldurchfuehrungsgebiet> gebieteLoader,
                             Loader<Gruppe> gruppenLoader,
                             Loader<GruppeImGebiet> gruppenImGebietLoader,
                             Loader<Wahlvorschlag> wahlvorschlaegeLoader,
                             Loader<Kandidatur> kandidaturenLoader,
                             Loader<PersonenVerknuepfung> personenVerknuepfungenLoader,
                             StimmenLoader stimmenLoader,
                             GewaehlteLoader gewaehlteLoader,
                             SitzeLoader sitzeLoader,
                             Loader<StaatenGruppe> staatenGruppenLoader,
                             Loader<Gebietsgruppierung> gebietsgruppierungenLoader,
                             Loader<WahlvorschlagsPerson> wahlvorschlagsPersonenLoader,
                             Loader<Wahlausschussmitglied> wahlausschussmitgliederLoader,
                             Loader<WahlausschussEntschaedigung> wahlausschussEntschaedigungenLoader,
                             Ergebnis ergebnis,
                             Ergebnis ergebnisVorperiode,
                             StimmenPool stimmen,
                             SystemGruppeEigenschaften systemGruppeEigenschaften,
                             StimmenKumulierer stimmenKumulierer,
                             AbstractWahlParameterLoader wahlParameterLoader,
                             ZulassungPruefer zulassungPruefer,
                             StimmzettelFormatter stimmzettelFormatter,
                             EntityAufStimmzettelDatenStimmzettelPositionBerechnung entityAufStimmzettelDatenStimmzettelPositionBerechnung,
                             GruppeImGebietReihenfolgeVorsortierer gruppeImGebietReihenfolgeVorsortierer,
                             Loader<GebietPolygonPoint> gebietPolygonPointsLoader,
                             Loader<Fremdkandidatur> fremdkandidaturenLoader,
                             Loader<InternetSeite> internetSeitenLoader,
                             Loader<ErgebnisKonflikt> konflikteLoader,
                             Loader<ErgebnisLogEintrag> ergebnisLogeintraegeLoader,
                             Loader<DHondtQuotient> dHondtQuotientenLoader,
                             Loader<ErgebnisGueltigerEingang> gueltigerEingaengeLoader,
                             Loader<Gebiet> erfassteGebieteLoader,
                             ErgebnisStimmenFilter ergebnisStimmenFilter,
                             ParameterLoader<Ergebniseingang, Ergebniseingangsart> letzterErgebniseingangLoader,
                             ParameterLoader<ErgebnisGueltigerEingang, Ergebniseingangsart> ergebnisGueltigerEingangLoader,
                             Loader<WahlbeteiligungVerlauf> wahlbeteiligungVerlaeufeLoader,
                             Loader<WahlbeteiligungAuswertung> wahlbeteiligungAuswertungenLoader,
                             StimmeingabeErfassenDescriptionResolver stimmeingabeErfassenDescriptionResolver,
                             Loader<StimmeingabePlausiKonfiguration> stimmeingabePlausiKonfigurationenLoader,
                             Loader<Veranstaltung> veranstaltungenLoader,
                             Loader<Stimmzettel> stimmzettelLoader,
                             Loader<StimmzettelKopfdatum> stimmzettelKopfdatenLoader,
                             Loader<Pruefkriterium> pruefkriterienLoader,
                             Loader<Wahlrechtspruefung> wahlrechtspruefungenLoader,
                             Loader<WvpWarnung> wvpWarnungenLoader,
                             Loader<PersonPruefungKonfiguration> personPruefungKonfigurationLoader,
                             Loader<Niederschrift> niederschriftLoader,
                             Loader<Aufgabe> aufgabeLoader) {
    super(wahl, gebieteLoader, gruppenLoader, gruppenImGebietLoader, wahlvorschlaegeLoader, kandidaturenLoader, personenVerknuepfungenLoader, stimmenLoader,
        gewaehlteLoader,
        sitzeLoader, staatenGruppenLoader, gebietsgruppierungenLoader, wahlvorschlagsPersonenLoader, wahlausschussmitgliederLoader,
        wahlausschussEntschaedigungenLoader, ergebnis,
        ergebnisVorperiode, stimmen, systemGruppeEigenschaften, stimmenKumulierer, wahlParameterLoader, zulassungPruefer, stimmzettelFormatter,
        entityAufStimmzettelDatenStimmzettelPositionBerechnung,
        gruppeImGebietReihenfolgeVorsortierer, gebietPolygonPointsLoader, fremdkandidaturenLoader, internetSeitenLoader, erfassteGebieteLoader,
        ergebnisStimmenFilter, letzterErgebniseingangLoader,
        ergebnisGueltigerEingangLoader, wahlbeteiligungVerlaeufeLoader, wahlbeteiligungAuswertungenLoader, stimmeingabeErfassenDescriptionResolver,
        stimmeingabePlausiKonfigurationenLoader,
        veranstaltungenLoader, stimmzettelLoader, stimmzettelKopfdatenLoader, pruefkriterienLoader, wahlrechtspruefungenLoader, wvpWarnungenLoader,
        personPruefungKonfigurationLoader, niederschriftLoader, aufgabeLoader);

    this.konflikteLoader = konflikteLoader;
    this.ergebnisLogeintraegeLoader = ergebnisLogeintraegeLoader;
    this.dHondtQuotientenLoader = dHondtQuotientenLoader;
    this.gueltigerEingaengeLoader = gueltigerEingaengeLoader;
  }

  public List<DHondtQuotient> getdHondtQuotienten() {
    if (dHondtQuotienten == null) {
      LOG.info("Lade dHondtQuotienten");
      dHondtQuotienten = dHondtQuotientenLoader.load();
      LOG.info("Lade dHondtQuotienten - done");

    }
    return dHondtQuotienten;
  }

  public List<ErgebnisLogEintrag> getErgebnisLogeintraege() {
    if (ergebnisLogeintraege == null) {
      LOG.info("Lade ergebnisLogeintraege");
      ergebnisLogeintraege = ergebnisLogeintraegeLoader.load();
      LOG.info("Lade ergebnisLogeintraege - done");
    }
    return ergebnisLogeintraege;
  }

  public List<Gewaehlt> getGewaehlte(Predicate<Gewaehlt> gewaehltPredicate) {
    return getGewaehlte().stream().filter(gewaehltPredicate).collect(Collectors.toList());
  }

  public List<Gewaehlt> getGewaehlte() {
    return getGewaehlte(getErgebnis().getErgebnisart());
  }

  public List<ErgebnisGueltigerEingang> getGueltigerEingaenge() {
    if (gueltigerEingaenge == null) {
      LOG.info("Lade gueltigerEingaenge");
      gueltigerEingaenge = gueltigerEingaengeLoader.load();
      LOG.info("Lade gueltigerEingaenge - done, gueltigerEingaenge=" + gueltigerEingaenge.size());
    }
    return gueltigerEingaenge;
  }

  public List<ErgebnisKonflikt> getKonflikte() {
    if (konflikte == null) {
      LOG.info("Lade konflikte");
      konflikte = konflikteLoader.load();
      LOG.info("Lade konflikte - done, konflikte=" + konflikte.size());

    }
    return konflikte;
  }

  public List<Sitze> getSitze() {
    return getSitze(getErgebnis().getErgebnisart());
  }

  protected Loader<DHondtQuotient> getdHondtQuotientenLoader() {
    return dHondtQuotientenLoader;
  }

  protected Loader<ErgebnisLogEintrag> getErgebnisLogeintraegeLoader() {
    return ergebnisLogeintraegeLoader;
  }

  protected Loader<ErgebnisGueltigerEingang> getGueltigerEingaengeLoader() {
    return gueltigerEingaengeLoader;
  }

  protected Loader<ErgebnisKonflikt> getKonflikteLoader() {
    return konflikteLoader;
  }

}
