
package de.ivu.elect.presentation.ergebnis.dokumente.gesamtergebnis;

import static de.ivu.elect.dokumente.DokumentFormatter.formatNumber;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import de.ivu.document.generator.template.annotations.DocumentComplexField;
import de.ivu.document.generator.template.annotations.DocumentSimpleField;
import de.ivu.elect.business.ergebnis.control.AbstractErgebnisDatenWahlberechtigte;
import de.ivu.elect.business.ergebnis.control.ErgebnisDaten;
import de.ivu.elect.business.ergebnis.control.ErgebnisDatenGueltige;
import de.ivu.elect.business.ergebnis.control.ErgebnisDatenStimmzettel;
import de.ivu.elect.business.ergebnis.control.ErgebnisDatenWaehler;
import de.ivu.elect.business.ergebnis.entity.Ergebnisart;
import de.ivu.elect.business.ergebnis.entity.Sitze;
import de.ivu.elect.business.ergebniskonflikt.entity.ErgebnisKonflikt;
import de.ivu.elect.business.gebietsbaum.control.GebietByBreadthFirstComparator;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.internet.control.GebietUndStimmabgabeart;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingabestatus;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.Listenverbindung;
import de.ivu.elect.dokumente.CoreElectContext;
import de.ivu.elect.dokumente.DokumentFormatter;
import de.ivu.elect.dokumente.gebiet.GebietDokument;
import de.ivu.elect.presentation.system.PercentUtil;

public class GebietMitStimmenDocument extends GebietDokument {

  private static final long serialVersionUID = 1L;

  @DocumentSimpleField("AnzahlWahlberechtigteOhneWahlschein")
  public final Long anzahlWahlberechtigteOhneWahlschein;

  @DocumentSimpleField("AnzahlWahlberechtigteOhneWahlscheinFormatiert")
  public final String anzahlWahlberechtigteOhneWahlscheinFormatiert;

  // ELECT-4246 Interessant für Berliner Wahlbuch...
  @DocumentSimpleField("AnzahlWahlberechtigteOhneWahlscheinAnteil")
  public final BigDecimal anzahlWahlberechtigteOhneWahlscheinProzent;

  @DocumentSimpleField("AnzahlWahlberechtigteMitWahlschein")
  public final Long anzahlWahlberechtigteMitWahlschein;

  @DocumentSimpleField("AnzahlWahlberechtigteMitWahlscheinFormatiert")
  public final String anzahlWahlberechtigteMitWahlscheinFormatiert;

  // ELECT-4246 Interessant für Berliner Wahlbuch...
  @DocumentSimpleField("AnzahlWahlberechtigteMitWahlscheinAnteil")
  public final BigDecimal anzahlWahlberechtigteMitWahlscheinProzent;

  @DocumentSimpleField("AnzahlWahlberechtigteNichtImWaehlerverzeichnis")
  public final Long anzahlWahlberechtigteNichtImWaehlerverzeichnis;

  @DocumentSimpleField("AnzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert")
  public final String anzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert;

  // ELECT-4246 Interessant für Berliner Wahlbuch...
  @DocumentSimpleField("AnzahlWahlberechtigteNichtImWaehlerverzeichnisAnteil")
  public final BigDecimal anzahlWahlberechtigteNichtImWaehlerverzeichnisProzent;

  @DocumentSimpleField("AnzahlWahlberechtigteGesamt")
  public final Long anzahlWahlberechtigteGesamt;

  @DocumentSimpleField("AnzahlWahlberechtigteGesamtFormatiert")
  public final String anzahlWahlberechtigteGesamtFormatiert;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteOhneWahlschein
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1")
  public final Long anzahlWahlberechtigteA1;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteOhneWahlscheinProzent
   */
  @Deprecated
  @DocumentSimpleField("WahlberechtigteA1Prozent")
  public final BigDecimal wahlberechtigteA1Prozent;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteOhneWahlscheinFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1Formatiert")
  public final String anzahlWahlberechtigteA1Formatiert;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteMitWahlschein
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA2")
  public final Long anzahlWahlberechtigteA2;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteMitWahlscheinProzent
   */
  @Deprecated
  @DocumentSimpleField("WahlberechtigteA2Prozent")
  public final BigDecimal wahlberechtigteA2Prozent;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteMitWahlscheinFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA2Formatiert")
  public final String anzahlWahlberechtigteA2Formatiert;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteNichtImWaehlerverzeichnis
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA3")
  public final Long anzahlWahlberechtigteA3;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA3Formatiert")
  public final String anzahlWahlberechtigteA3Formatiert;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteGesamt
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1A2")
  public final Long anzahlWahlberechtigteA1A2;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteGesamtFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1A2Formatiert")
  public final String anzahlWahlberechtigteA1A2Formatiert;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteGesamt
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1A2A3")
  public final Long anzahlWahlberechtigteA1A2A3;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWahlberechtigteGesamtFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWahlberechtigteA1A2A3Formatiert")
  public final String anzahlWahlberechtigteA1A2A3Formatiert;

  @DocumentSimpleField("AnzahlWählerMitWahlschein")
  public final Long anzahlWaehlerMitWahlschein;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinFormatiert")
  public final String anzahlWaehlerMitWahlscheinFormatiert;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinAnteilAusUrnenwahl")
  public final Long anzahlWaehlerMitWahlscheinAnteilAusUrnenwahl;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinAnteilAusUrnenwahlFormatiert")
  public final String anzahlWaehlerMitWahlscheinAnteilAusUrnenwahlFormatiert;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinAnteilAusBriefwahl")
  public final Long anzahlWaehlerMitWahlscheinAnteilAusBriefwahl;

  @DocumentSimpleField("AnzahlWählerMitWahlscheinAnteilAusBriefwahlFormatiert")
  public final String anzahlWaehlerMitWahlscheinAnteilAusBriefwahlFormatiert;

  @DocumentSimpleField("AnzahlWählerMitVollmacht")
  public final Long anzahlWaehlerMitVollmacht;

  @DocumentSimpleField("AnzahlWählerMitVollmachtFormatiert")
  public final String anzahlWaehlerMitVollmachtFormatiert;

  @DocumentSimpleField("AnzahlWählerOhneWahlschein")
  public final Long anzahlWaehlerOhneWahlschein;

  @DocumentSimpleField("AnzahlWählerOhneWahlscheinFormatiert")
  public final String anzahlWaehlerOhneWahlscheinFormatiert;

  @DocumentSimpleField("AnzahlWählerGesamt")
  public final Long anzahlWaehlerGesamt;

  @DocumentSimpleField("AnzahlWählerGesamtFormatiert")
  public final String anzahlWaehlerGesamtFormatiert;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWaehlerMitWahlscheinAnteilAusBriefwahl
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWählerMitWahlscheinAusBriefwahlbezirkErfasstInUrnenwahlbezirk")
  public final Long anzahlWaehlerAusBriefwahlbezirkErfasstInUrnenwahlbezirk;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWaehlerMitWahlscheinAnteilAusBriefwahlFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlWählerMitWahlscheinAusBriefwahlbezirkErfasstInUrnenwahlbezirkFormatiert")
  public final String anzahlWaehlerAusBriefwahlbezirkErfasstInUrnenwahlbezirkFormatiert;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlWaehlerMitWahlscheinAnteilAusBriefwahl
   */
  @Deprecated
  @DocumentSimpleField("AnzahlBriefwählerInUrne")
  public final Long anzahlBriefwaehlerInUrne;

  // ELECTDD-331 - B2 Werte müssen erfasst werden können
  @DocumentSimpleField("BriefwahlInUrneErfassenInGebietOderDarunter")
  public final boolean briefwahlInUrneErfassenInGebietOderDarunter;

  // ELECTDD-331 - B2 Werte müssen erfasst werden können
  @DocumentSimpleField("BriefwahlInUrneErfassenAufGebiet")
  public final boolean briefwahlInUrneErfassenAufGebiet;

  @DocumentSimpleField("AnzahlDirektstimmenGültig")
  public final Long anzahlGueltigeDirektstimmen;

  @DocumentSimpleField("AnzahlDirektstimmenGültigFormatiert")
  public final String anzahlGueltigeDirektstimmenFormatiert;

  @DocumentSimpleField("AnzahlDirektstimmenUngültig")
  public final Long anzahlUngueltigeDirektstimmen;

  @DocumentSimpleField("AnzahlDirektstimmenUngültigFormatiert")
  public final String anzahlUngueltigeDirektstimmenFormatiert;

  @DocumentSimpleField("AnzahlDirektstimmenGesamt")
  public final Long anzahlGesamtDirektstimmen;

  @DocumentSimpleField("AnzahlDirektstimmenGesamtFormatiert")
  public final String anzahlGesamtDirektstimmenFormatiert;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlGesamtDirektstimmen
   */
  @Deprecated
  @DocumentSimpleField("AnzahlGültigeUndUngültigeDirektstimmen")
  public final Long anzahlGueltigeUndUngueltigeDirektstimmen;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlGesamtDirektstimmenFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlGültigeUndUngültigeDirektstimmenFormatiert")
  public final String anzahlGueltigeUndUngueltigeDirektstimmenFormatiert;

  @DocumentSimpleField("AnzahlListenstimmenGültig")
  public final Long anzahlGueltigeListenstimmen;

  @DocumentSimpleField("AnzahlListenstimmenGültigFormatiert")
  public final String anzahlGueltigeListenstimmenFormatiert;

  @DocumentSimpleField("AnzahlListenstimmenUngültig")
  public final Long anzahlUngueltigeListenstimmen;

  @DocumentSimpleField("AnzahlListenstimmenUngültigFormatiert")
  public final String anzahlUngueltigeListenstimmenFormatiert;

  @DocumentSimpleField("AnzahlListenstimmenGesamt")
  public final Long anzahlGesamtListenstimmen;

  @DocumentSimpleField("AnzahlListenstimmenGesamtFormatiert")
  public final String anzahlGesamtListenstimmenFormatiert;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlGesamtListenstimmen
   */
  @Deprecated
  @DocumentSimpleField("AnzahlGültigeUndUngültigeListenstimmen")
  public final Long anzahlGueltigeUndUngueltigeListenstimmen;

  /**
   * @deprecated
   * @see GebietMitStimmenDocument#anzahlGesamtListenstimmenFormatiert
   */
  @Deprecated
  @DocumentSimpleField("AnzahlGültigeUndUngültigeListenstimmenFormatiert")
  public final String anzahlGueltigeUndUngueltigeListenstimmenFormatiert;

  @DocumentSimpleField("AnzahlStimmzettelGültig")
  public final Long anzahlGueltigeStimmzettel;

  @DocumentSimpleField("AnzahlStimmzettelGültigFormatiert")
  public final String anzahlGueltigeStimmzettelFormatiert;

  @DocumentSimpleField("AnzahlStimmzettelUngültig")
  public final Long anzahlUngueltigeStimmzettel;

  @DocumentSimpleField("AnzahlStimmzettelUngültigFormatiert")
  public final String anzahlUngueltigeStimmzettelFormatiert;

  @DocumentSimpleField("AnzahlStimmzettelGesamt")
  public final Long anzahlGesamtStimmzettel;

  @DocumentSimpleField("AnzahlStimmzettelGesamtFormatiert")
  public final String anzahlGesamtStimmzettelFormatiert;

  @DocumentSimpleField("AnzahlZuvergebenerSitze")
  public final Long anzahlZuvergebenerSitze;

  @DocumentSimpleField("AnzahlVergebeneSitze")
  public final Long anzahlVergebeneSitze;

  @DocumentSimpleField("AnzahlBriefwahlgebiete")
  public final Long anzahlBriefwahlgebiete;

  @DocumentSimpleField("AnzahlUrnenwahlgebiete")
  public final Long anzahlUrnenwahlgebiete;

  @DocumentSimpleField("AnzahlSonderwahlgebiete")
  public final Long anzahlSonderwahlgebiete;

  @DocumentSimpleField("AnzahlErfassungsgebiete")
  public final Long anzahlErfassungsgebiete;

  @DocumentSimpleField("Wahlbeteiligung")
  public final BigDecimal wahlbeteiligung;

  @DocumentSimpleField("WahlbeteiligungFormatiert")
  public final String wahlbeteiligungFormatiert;

  // ELECT-3760
  @DocumentComplexField("Zwischensummen-Urnenwahlbezirke")
  public final ZwischensummenAufGebietDocument zwischensummenUrnenwaehler;

  // ELECT-3760
  @DocumentComplexField("Zwischensummen-Briefwahlbezirke")
  public final ZwischensummenAufGebietDocument zwischensummenBriefwaehler;

  @DocumentComplexField("Zwischensummen-Sonderstimmbezirke")
  public final ZwischensummenAufGebietDocument zwischensummenSonderwahlgebiete;

  @DocumentSimpleField("Ist-Ergebniseingabestatus-Komplett-Eingabe-Beendet")
  public boolean ergebniseingabestatusKomplettEingabeBeendet;

  @DocumentSimpleField("Ist-Ergebniseingabestatus-Komplett-Gesperrt")
  public boolean ergebniseingabestatusKomplettGesperrt;

  @DocumentSimpleField("Ist-Ergebniseingabestatus-Komplett-Abgeschlossen")
  public boolean ergebniseingabestatusKomplettAbgeschlossen;

  @DocumentSimpleField("Ist-Ergebniseingabestatus-Komplett-Freigegeben")
  public boolean ergebniseingabestatusKomplettFreigegeben;

  @DocumentSimpleField("Ist-Ergebniseingabestatus-Komplett-Ausbleibend")
  public boolean ergebniseingabestatusKomplettAusbleibend;

  @DocumentSimpleField("Ist-wird-in-anderem-Gebiet-erfasst")
  public final boolean isWirdInAnderemGebietErfasst;

  @DocumentSimpleField("Ist-erfasst-andere-Gebiete")
  public final boolean isErfasstAndereGebiet;

  @DocumentSimpleField("Wird-erfasst-in-Gebiet")
  public final String wirdErfasstInGebiet;

  @DocumentSimpleField("Erfasst-auch-fuer-Gebiete")
  public final String erfasstAuchFuerGebiete;

  public GebietMitStimmenDocument(CoreElectContext coreElectContext, ErgebnisDaten ergebnisDaten, GebietUndStimmabgabeart gebietUndStimmabgabeart) {
    super(coreElectContext, gebietUndStimmabgabeart.getWahldurchfuehrungsgebiet());

    Locale locale = coreElectContext.getLocale();

    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = gebietUndStimmabgabeart.getWahldurchfuehrungsgebiet();

    AbstractErgebnisDatenWahlberechtigte ergebnisDatenWahlberechtigte = ergebnisDaten.getErgebnisDatenWahlberechtigte();

    this.anzahlWahlberechtigteOhneWahlschein = ergebnisDatenWahlberechtigte.getSummeWahlberechtigteOhneWahlschein(gebietUndStimmabgabeart);
    this.anzahlWahlberechtigteOhneWahlscheinFormatiert = formatNumber(this.anzahlWahlberechtigteOhneWahlschein, locale);
    this.anzahlWahlberechtigteMitWahlschein = ergebnisDatenWahlberechtigte.getSummeWahlberechtigteMitWahlschein(gebietUndStimmabgabeart);
    this.anzahlWahlberechtigteMitWahlscheinFormatiert = formatNumber(this.anzahlWahlberechtigteMitWahlschein, locale);
    this.anzahlWahlberechtigteNichtImWaehlerverzeichnis = ergebnisDatenWahlberechtigte.getSummeWahlberechtigteNichtImWaehlerverzeichnis(gebietUndStimmabgabeart);
    this.anzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert = formatNumber(this.anzahlWahlberechtigteNichtImWaehlerverzeichnis, locale);
    this.anzahlWahlberechtigteGesamt = ergebnisDatenWahlberechtigte.getSummeWahlberechtigteGesamt(gebietUndStimmabgabeart);
    this.anzahlWahlberechtigteGesamtFormatiert = formatNumber(this.anzahlWahlberechtigteGesamt, locale);

    // ELECT-4246 Interessant für Berliner Wahlbuch...
    this.anzahlWahlberechtigteOhneWahlscheinProzent = PercentUtil.percent(this.anzahlWahlberechtigteGesamt, this.anzahlWahlberechtigteOhneWahlschein);
    this.anzahlWahlberechtigteMitWahlscheinProzent = PercentUtil.percent(this.anzahlWahlberechtigteGesamt, this.anzahlWahlberechtigteMitWahlschein);
    this.anzahlWahlberechtigteNichtImWaehlerverzeichnisProzent = PercentUtil.percent(this.anzahlWahlberechtigteGesamt, this.anzahlWahlberechtigteNichtImWaehlerverzeichnis);

    // LEGACY!!!
    this.anzahlWahlberechtigteA1 = this.anzahlWahlberechtigteOhneWahlschein;
    this.anzahlWahlberechtigteA1Formatiert = this.anzahlWahlberechtigteOhneWahlscheinFormatiert;
    this.anzahlWahlberechtigteA2 = this.anzahlWahlberechtigteMitWahlschein;
    this.anzahlWahlberechtigteA2Formatiert = this.anzahlWahlberechtigteMitWahlscheinFormatiert;
    this.anzahlWahlberechtigteA3 = this.anzahlWahlberechtigteNichtImWaehlerverzeichnis;
    this.anzahlWahlberechtigteA3Formatiert = this.anzahlWahlberechtigteNichtImWaehlerverzeichnisFormatiert;
    this.anzahlWahlberechtigteA1A2 = sum(this.anzahlWahlberechtigteOhneWahlschein, this.anzahlWahlberechtigteMitWahlschein);
    this.anzahlWahlberechtigteA1A2Formatiert = formatNumber(this.anzahlWahlberechtigteA1A2, locale);
    this.anzahlWahlberechtigteA1A2A3 = sum(sum(this.anzahlWahlberechtigteOhneWahlschein, this.anzahlWahlberechtigteMitWahlschein), this.anzahlWahlberechtigteNichtImWaehlerverzeichnis);
    this.anzahlWahlberechtigteA1A2A3Formatiert = formatNumber(this.anzahlWahlberechtigteA1A2A3, locale);

    this.wahlberechtigteA1Prozent = this.anzahlWahlberechtigteOhneWahlscheinProzent;
    this.wahlberechtigteA2Prozent = this.anzahlWahlberechtigteMitWahlscheinProzent;

    ErgebnisDatenWaehler ergebnisDatenWaehler = ergebnisDaten.getErgebnisDatenWaehler();

    this.anzahlWaehlerOhneWahlschein = ergebnisDatenWaehler.getSummeWaehlerOhneWahlschein(gebietUndStimmabgabeart);
    this.anzahlWaehlerOhneWahlscheinFormatiert = formatNumber(this.anzahlWaehlerOhneWahlschein, locale);

    this.anzahlWaehlerMitWahlschein = ergebnisDatenWaehler.getSummeWaehlerMitWahlschein(gebietUndStimmabgabeart);
    this.anzahlWaehlerMitWahlscheinFormatiert = formatNumber(this.anzahlWaehlerMitWahlschein, locale);
    this.anzahlWaehlerMitWahlscheinAnteilAusUrnenwahl = ergebnisDatenWaehler.getSummeWaehlerMitWahlscheinInUrnenwahlAnteilAusUrnenwahl(gebietUndStimmabgabeart);
    this.anzahlWaehlerMitWahlscheinAnteilAusUrnenwahlFormatiert = formatNumber(this.anzahlWaehlerMitWahlscheinAnteilAusUrnenwahl, locale);
    this.anzahlWaehlerMitWahlscheinAnteilAusBriefwahl = ergebnisDatenWaehler.getSummeWaehlerMitWahlscheinInUrnenwahlAnteilAusBriefwahl(gebietUndStimmabgabeart);
    this.anzahlWaehlerMitWahlscheinAnteilAusBriefwahlFormatiert = formatNumber(this.anzahlWaehlerMitWahlscheinAnteilAusBriefwahl, locale);
    this.anzahlWaehlerAusBriefwahlbezirkErfasstInUrnenwahlbezirk = this.anzahlWaehlerMitWahlscheinAnteilAusBriefwahl;
    this.anzahlWaehlerAusBriefwahlbezirkErfasstInUrnenwahlbezirkFormatiert = this.anzahlWaehlerMitWahlscheinAnteilAusBriefwahlFormatiert;
    this.anzahlBriefwaehlerInUrne = this.anzahlWaehlerMitWahlscheinAnteilAusBriefwahl;

    this.anzahlWaehlerMitVollmacht = ergebnisDatenWaehler.getSummeWaehlerMitVollmacht(gebietUndStimmabgabeart);
    this.anzahlWaehlerMitVollmachtFormatiert = formatNumber(this.anzahlWaehlerMitVollmacht, locale);

    this.anzahlWaehlerGesamt = ergebnisDatenWaehler.getSummeWaehlerGesamt(gebietUndStimmabgabeart);
    this.anzahlWaehlerGesamtFormatiert = formatNumber(this.anzahlWaehlerGesamt, locale);

    // ELECTDD-331 - B2 Werte müssen erfasst werden können
    this.briefwahlInUrneErfassenInGebietOderDarunter = wahldurchfuehrungsgebiet.isBriefwahlInUrneErfassenInGebietOderDarunter();
    this.briefwahlInUrneErfassenAufGebiet = wahldurchfuehrungsgebiet.getBriefwahlInUrneErfassen();

    ErgebnisDatenGueltige ergebnisDatenGueltige = ergebnisDaten.getErgebnisDatenGueltige();

    this.anzahlGueltigeDirektstimmen = ergebnisDatenGueltige.getErststimmenAktuellGueltig(gebietUndStimmabgabeart);
    this.anzahlGueltigeDirektstimmenFormatiert = formatNumber(this.anzahlGueltigeDirektstimmen, locale);
    this.anzahlUngueltigeDirektstimmen = ergebnisDatenGueltige.getErststimmenAktuellUngueltig(gebietUndStimmabgabeart);
    this.anzahlUngueltigeDirektstimmenFormatiert = formatNumber(this.anzahlUngueltigeDirektstimmen, locale);
    this.anzahlGesamtDirektstimmen = ergebnisDatenGueltige.getErststimmenAktuellGesamt(gebietUndStimmabgabeart);
    this.anzahlGesamtDirektstimmenFormatiert = formatNumber(this.anzahlGesamtDirektstimmen, locale);

    this.anzahlGueltigeListenstimmen = ergebnisDatenGueltige.getZweitstimmenAktuellGueltig(gebietUndStimmabgabeart);
    this.anzahlGueltigeListenstimmenFormatiert = formatNumber(this.anzahlGueltigeListenstimmen, locale);
    this.anzahlUngueltigeListenstimmen = ergebnisDatenGueltige.getZweitstimmenAktuellUngueltig(gebietUndStimmabgabeart);
    this.anzahlUngueltigeListenstimmenFormatiert = formatNumber(this.anzahlUngueltigeListenstimmen, locale);
    this.anzahlGesamtListenstimmen = ergebnisDatenGueltige.getZweitstimmenAktuellGesamt(gebietUndStimmabgabeart);
    this.anzahlGesamtListenstimmenFormatiert = formatNumber(this.anzahlGesamtListenstimmen, locale);

    ErgebnisDatenStimmzettel ergebnisDatenStimmzettel = ergebnisDaten.getErgebnisDatenStimmzettel();

    this.anzahlGueltigeStimmzettel = ergebnisDatenStimmzettel.getStimmzettelAktuellGueltig(gebietUndStimmabgabeart);
    this.anzahlGueltigeStimmzettelFormatiert = formatNumber(this.anzahlGueltigeStimmzettel, locale);
    this.anzahlUngueltigeStimmzettel = ergebnisDatenStimmzettel.getStimmzettelAktuellUngueltig(gebietUndStimmabgabeart);
    this.anzahlUngueltigeStimmzettelFormatiert = formatNumber(this.anzahlUngueltigeStimmzettel, locale);
    this.anzahlGesamtStimmzettel = ergebnisDatenStimmzettel.getStimmzettelAktuellGesamt(gebietUndStimmabgabeart);
    this.anzahlGesamtStimmzettelFormatiert = formatNumber(this.anzahlGesamtStimmzettel, locale);

    // LEGACY!!! - ELECT-4246 Interessant für Berliner Wahlbuch...
    this.anzahlGueltigeUndUngueltigeDirektstimmen = this.anzahlGesamtDirektstimmen;
    this.anzahlGueltigeUndUngueltigeDirektstimmenFormatiert = this.anzahlGesamtDirektstimmenFormatiert;
    this.anzahlGueltigeUndUngueltigeListenstimmen = this.anzahlGesamtListenstimmen;
    this.anzahlGueltigeUndUngueltigeListenstimmenFormatiert = this.anzahlGesamtListenstimmenFormatiert;

    this.anzahlZuvergebenerSitze = wahldurchfuehrungsgebiet.getAnzahlSitze();
    this.anzahlVergebeneSitze = summiereVergebeneSitzeFuerGebiet(ergebnisDaten, wahldurchfuehrungsgebiet);

    Long anzahlUntergeordneteErfassungsgebiete = 0L;

    List<Wahldurchfuehrungsgebiet> untergeordneteUrnenwahlbezirke = new ArrayList<>();
    List<Wahldurchfuehrungsgebiet> untergeordneteBriefwahlbezirke = new ArrayList<>();
    List<Wahldurchfuehrungsgebiet> untergeordneteSonderstimmbezirke = new ArrayList<>();

    this.ergebniseingabestatusKomplettEingabeBeendet = true;
    this.ergebniseingabestatusKomplettGesperrt = true;
    this.ergebniseingabestatusKomplettAbgeschlossen = true;
    this.ergebniseingabestatusKomplettFreigegeben = true;
    this.ergebniseingabestatusKomplettAusbleibend = true;

    for (Wahldurchfuehrungsgebiet erfassungsgebiet : ergebnisDaten.getErfassungsgebiete()) {
      if (erfassungsgebiet.isUntergebietVon(wahldurchfuehrungsgebiet)) {
        anzahlUntergeordneteErfassungsgebiete++;

        if (erfassungsgebiet.isBriefwahlgebiet()) {
          untergeordneteBriefwahlbezirke.add(erfassungsgebiet);
        } else if (Boolean.TRUE.equals(erfassungsgebiet.getSonderstimmbezirk())) { // NOTE, dass Sonderwahlbezirke fachlich gleichwertig wie Urnen- und Briefwahlgebiete zu behandeln sind. gab
          untergeordneteSonderstimmbezirke.add(erfassungsgebiet); // ELECT-3768 Sonderwahlbezirke eigenständiger Gebietstyp in LTW DD
        } else {
          untergeordneteUrnenwahlbezirke.add(erfassungsgebiet);
        }

        Ergebnisart ergebnisart = ergebnisDaten.getErgebnis().getErgebnisart();

        // ELECT-9400
        this.ergebniseingabestatusKomplettEingabeBeendet &= erfassungsgebiet.matchesAnyErgebniseingabestatusInUebergeordneterGebietshierarchie(ergebnisart, Ergebniseingabestatus::isEingabeBeendet);
        this.ergebniseingabestatusKomplettGesperrt &= erfassungsgebiet.matchesAnyErgebniseingabestatusInUebergeordneterGebietshierarchie(ergebnisart, Ergebniseingabestatus::isGesperrt);
        this.ergebniseingabestatusKomplettAbgeschlossen &= erfassungsgebiet.matchesAnyErgebniseingabestatusInUebergeordneterGebietshierarchie(ergebnisart, Ergebniseingabestatus::isAbgeschlossen);
        this.ergebniseingabestatusKomplettFreigegeben &= erfassungsgebiet.matchesAnyErgebniseingabestatusInUebergeordneterGebietshierarchie(ergebnisart, Ergebniseingabestatus::isFreigegeben);
        this.ergebniseingabestatusKomplettAusbleibend &= erfassungsgebiet.matchesAnyErgebniseingabestatusInUebergeordneterGebietshierarchie(ergebnisart, Ergebniseingabestatus::isAusbleibend);
      }
    }

    this.anzahlErfassungsgebiete = anzahlUntergeordneteErfassungsgebiete;

    this.anzahlUrnenwahlgebiete = (long) untergeordneteUrnenwahlbezirke.size();
    this.zwischensummenUrnenwaehler = new ZwischensummenAufGebietDocument(coreElectContext, ergebnisDaten, gebietUndStimmabgabeart, untergeordneteUrnenwahlbezirke);

    this.anzahlBriefwahlgebiete = (long) untergeordneteBriefwahlbezirke.size();
    this.zwischensummenBriefwaehler = new ZwischensummenAufGebietDocument(coreElectContext, ergebnisDaten, gebietUndStimmabgabeart, untergeordneteBriefwahlbezirke);

    this.anzahlSonderwahlgebiete = (long) untergeordneteSonderstimmbezirke.size();
    this.zwischensummenSonderwahlgebiete = new ZwischensummenAufGebietDocument(coreElectContext, ergebnisDaten, gebietUndStimmabgabeart, untergeordneteSonderstimmbezirke);

    this.wahlbeteiligung = PercentUtil.percent(this.anzahlWahlberechtigteGesamt, this.anzahlWaehlerGesamt);
    this.wahlbeteiligungFormatiert = DokumentFormatter.formatProzent(this.wahlbeteiligung, locale);

    this.isWirdInAnderemGebietErfasst = wahldurchfuehrungsgebiet.getErfasstIn() != null;
    List<Wahldurchfuehrungsgebiet> erfasstFuerListe = ergebnisDaten.getErfasstFuerGebiete(wahldurchfuehrungsgebiet);
    this.isErfasstAndereGebiet = !erfasstFuerListe.isEmpty();

    this.wirdErfasstInGebiet = Optional.ofNullable(wahldurchfuehrungsgebiet.getErfasstIn()).map(g -> coreElectContext.getGebietNummerFormatter().getDarstellung(g)).orElse("");

    this.erfasstAuchFuerGebiete = erfasstFuerListe.stream().sorted(GebietByBreadthFirstComparator.INSTANCE).map(g -> coreElectContext.getGebietNummerFormatter().getDarstellung(g))
        .collect(Collectors.joining(", "));

  }

  protected List<ErgebnisKonfliktDocument> erstelleKonflikte(CoreElectContext coreElectContext, ErgebnisDaten ergebnisDaten, GebietUndStimmabgabeart gebietUndStimmabgabeart,
      Map<Liste, ListeMitStimmergebnissenDocument> ergebnisDokumentPerListe, Map<Listenverbindung, WasListenverbindungDokument> ergebnisDokumentPerListenverbindung,
      Map<Kandidatur, KandidaturMitStimmergebnissenDocument> ergebnisDokumentPerKandidatur) {
    List<ErgebnisKonfliktDocument> result = new ArrayList<>();

    for (ErgebnisKonflikt ergebnisKonflikt : ergebnisDaten.getKonflikteFuerGebietUndDarunter(gebietUndStimmabgabeart.getWahldurchfuehrungsgebiet())) {
      result.add(new ErgebnisKonfliktDocument(coreElectContext, ergebnisDaten, ergebnisKonflikt, ergebnisDokumentPerListe, ergebnisDokumentPerListenverbindung, ergebnisDokumentPerKandidatur));
    }

    return result;
  }

  private Long summiereVergebeneSitzeFuerGebiet(ErgebnisDaten ergebnisDaten, Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    Long summeVergebeneSitze = 0L;

    List<Sitze> sitzes = ergebnisDaten.getSitzeFuerGebiet(wahldurchfuehrungsgebiet);

    for (Sitze sitze : sitzes) {
      summeVergebeneSitze += sitze.getAnzahl();
    }

    return summeVergebeneSitze;
  }
}
