
package de.ivu.elect.dokumente.wahlvorschlag;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import de.ivu.elect.business.exchange.control.AbstractContextMitCustomParameter;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.person.entity.PersonStatus;
import de.ivu.elect.business.pruefung.boundary.ZulassungPruefer;
import de.ivu.elect.business.stimmzettel.entity.EntityAufStimmzettelDaten;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahlausschuss.boundary.AbstractWahlausschussmitgliedDAO;
import de.ivu.elect.business.wahlausschuss.entity.AbstractWahlausschussmitglied;
import de.ivu.elect.business.wahlausschuss.entity.Wahlausschussmitglied;
import de.ivu.elect.business.wahlrechtspruefung.entity.Wahlrechtspruefung;
import de.ivu.elect.business.wahlvorschlag.boundary.AbstractWahlvorschlagDAO;
import de.ivu.elect.business.wahlvorschlag.control.WahlvorschlaegeDokumentGeneratorWahlrechtspruefungenFinder;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.business.wahlvorschlagsperson.boundary.AbstractWahlvorschlagsPersonDAO;
import de.ivu.elect.business.wahlvorschlagsperson.entity.WahlvorschlagsPerson;
import de.ivu.elect.dokumente.kandidatur.KandidaturCoreDaten;

public class WahlvorschlagCoreDaten {

  private final KandidaturCoreDaten kandidaturCoreDaten;

  private final EntityAufStimmzettelDaten entityAufStimmzettelDaten;

  private final Map<Gebiet, Collection<Wahlvorschlag>> wahlvorschlaegeInWahlPerGebiet;

  private final Map<Gruppe, Collection<Wahlvorschlag>> wahlvorschlaegeInWahlPerGruppe;

  private final Map<Gebiet, Collection<Wahlausschussmitglied>> wahlausschussmitgliederInWahlPerGebiet;

  private final Map<Wahlvorschlag, Collection<WahlvorschlagsPerson>> wahlvorschlagsPersonenPerWahlvorschlag;

  private final Map<Wahlvorschlag, Collection<Wahlrechtspruefung>> wahlrechtspruefungenPerWahlvorschlag;

  private final Map<Wahlvorschlag, Long> anzahlUnterstuetzerGeeignetGesamtPerWahlvorschlag;

  private final Map<Wahlvorschlag, Long> anzahlUnterstuetzerNichtGeeignetGesamtPerWahlvorschlag;

  public WahlvorschlagCoreDaten(Wahl wahl, AbstractWahlvorschlagDAO wahlvorschlagDAO, KandidaturCoreDaten kandidaturCoreDaten, AbstractWahlvorschlagsPersonDAO wahlvorschlagsPersonDAO,
      AbstractWahlausschussmitgliedDAO wahlausschussmitgliedDAO, WahlvorschlaegeDokumentGeneratorWahlrechtspruefungenFinder wahlvorschlaegeDokumentGeneratorWahlrechtspruefungenFinder,
      AbstractContextMitCustomParameter context) {
    super();

    this.kandidaturCoreDaten = kandidaturCoreDaten;

    this.entityAufStimmzettelDaten = kandidaturCoreDaten.getEntityAufStimmzettelDaten();

    this.wahlvorschlaegeInWahlPerGebiet = new HashMap<>();
    this.wahlvorschlaegeInWahlPerGruppe = new HashMap<>();

    this.wahlrechtspruefungenPerWahlvorschlag = new HashMap<>();

    this.wahlvorschlagsPersonenPerWahlvorschlag = new HashMap<>();

    this.anzahlUnterstuetzerGeeignetGesamtPerWahlvorschlag = new HashMap<>();
    this.anzahlUnterstuetzerNichtGeeignetGesamtPerWahlvorschlag = new HashMap<>();

    for (Wahlvorschlag wahlvorschlag : wahlvorschlagDAO.findByWahl(wahl)) {
      Gebiet gebiet = wahlvorschlag.getGebiet();

      this.wahlvorschlaegeInWahlPerGebiet.putIfAbsent(gebiet, new HashSet<>());
      this.wahlvorschlaegeInWahlPerGebiet.get(gebiet).add(wahlvorschlag);

      Gruppe gruppe = wahlvorschlag.getGruppe();

      this.wahlvorschlaegeInWahlPerGruppe.putIfAbsent(gruppe, new HashSet<>());
      this.wahlvorschlaegeInWahlPerGruppe.get(gruppe).add(wahlvorschlag);

      this.wahlrechtspruefungenPerWahlvorschlag.put(wahlvorschlag, wahlvorschlaegeDokumentGeneratorWahlrechtspruefungenFinder.findeWahlrechtspruefungen(wahlvorschlag, context));

      List<WahlvorschlagsPerson> wahlvorschlagsPersonen = new ArrayList<>();
      wahlvorschlagsPersonen.addAll(wahlvorschlagsPersonDAO.findByWahlvorschlagAndStatusOhneUnterstuetzer(wahlvorschlag, PersonStatus.GEEIGNET));
      wahlvorschlagsPersonen.addAll(wahlvorschlagsPersonDAO.findByWahlvorschlagAndStatusOhneUnterstuetzer(wahlvorschlag, PersonStatus.NICHT_ZU_PRUEFEN));

      this.wahlvorschlagsPersonenPerWahlvorschlag.put(wahlvorschlag, wahlvorschlagsPersonen);

      this.anzahlUnterstuetzerGeeignetGesamtPerWahlvorschlag.put(wahlvorschlag, wahlvorschlag.getAnzahlUnterstuetzerGeeignetGesamt(wahlvorschlagsPersonDAO));
      this.anzahlUnterstuetzerNichtGeeignetGesamtPerWahlvorschlag.put(wahlvorschlag, wahlvorschlag.getAnzahlUnterstuetzerNichtGeeignetGesamt(wahlvorschlagsPersonDAO));
    }

    this.wahlausschussmitgliederInWahlPerGebiet = new HashMap<>(AbstractWahlausschussmitglied.sortiereUndGruppiereNachGebiet(wahl, wahlausschussmitgliedDAO));
  }

  public KandidaturCoreDaten getKandidaturCoreDaten() {
    return kandidaturCoreDaten;
  }

  public EntityAufStimmzettelDaten getEntityAufStimmzettelDaten() {
    return entityAufStimmzettelDaten;
  }

  public ZulassungPruefer getZulassungPruefer() {
    return getEntityAufStimmzettelDaten().getZulassungPruefer();
  }

  public Map<Gebiet, Collection<Wahlvorschlag>> getWahlvorschlaegeInWahlPerGebiet() {
    return wahlvorschlaegeInWahlPerGebiet;
  }

  public Map<Gruppe, Collection<Wahlvorschlag>> getWahlvorschlaegeInWahlPerGruppe() {
    return wahlvorschlaegeInWahlPerGruppe;
  }

  public Map<Gebiet, Collection<Wahlausschussmitglied>> getWahlausschussmitgliederInWahlPerGebiet() {
    return wahlausschussmitgliederInWahlPerGebiet;
  }

  public Collection<Wahlrechtspruefung> getWahlrechtspruefungen(Wahlvorschlag wahlvorschlag) {
    return wahlrechtspruefungenPerWahlvorschlag.getOrDefault(wahlvorschlag, new HashSet<>());
  }

  public Collection<WahlvorschlagsPerson> getWahlvorschlagsPersonen(Wahlvorschlag wahlvorschlag) {
    return wahlvorschlagsPersonenPerWahlvorschlag.getOrDefault(wahlvorschlag, new HashSet<>());
  }

  public long getAnzahlUnterstuetzerGeeignetGesamt(Wahlvorschlag wahlvorschlag) {
    return fixNullToZero(anzahlUnterstuetzerGeeignetGesamtPerWahlvorschlag.getOrDefault(wahlvorschlag, 0L));
  }

  public long getAnzahlUnterstuetzerNichtGeeignetGesamt(Wahlvorschlag wahlvorschlag) {
    return fixNullToZero(anzahlUnterstuetzerNichtGeeignetGesamtPerWahlvorschlag.getOrDefault(wahlvorschlag, 0L));
  }

  private long fixNullToZero(Long value) {
    if (value == null) {
      return 0;
    }

    return value;
  }
}
