
package de.ivu.elect.was.exchange.wahl.aufteilen;

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

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

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.ivu.elect.business.ergebnis.control.StimmergebnisDaten;
import de.ivu.elect.business.gebietsbaum.boundary.GebietUebernehmen;
import de.ivu.elect.business.gebietsbaum.boundary.WahldurchfuehrungsgebietFactory;
import de.ivu.elect.business.gebietsbaum.control.GebietByBreadthFirstComparator;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietTK;
import de.ivu.elect.business.gebietsbaum.entity.GebietUebernehmenContext;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsgruppierung;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.boundary.GruppeFactory;
import de.ivu.elect.business.gruppe.boundary.PolitischeGruppeFactory;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppeimgebiet.boundary.GruppeImGebietFactory;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebietTK;
import de.ivu.elect.business.internet.entity.InternetSeite;
import de.ivu.elect.business.kandidatur.boundary.DirektkandidaturFactory;
import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturFactory;
import de.ivu.elect.business.kandidatur.entity.Direktkandidatur;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.konfiguration.entity.KonfigurationLoader;
import de.ivu.elect.business.konfiguration.entity.MandantKonfigurationWerte;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.person.entity.PersonenVerknuepfung;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiKonfiguration;
import de.ivu.elect.business.wahl.boundary.WahldurchfuehrungFactory;
import de.ivu.elect.business.wahl.boundary.WahlterminFactory;
import de.ivu.elect.business.wahl.control.WahlAufteiler;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.business.wahlbeteiligung.entity.Wahlbeteiligung;
import de.ivu.elect.business.wahlbeteiligung.entity.WahlbeteiligungAuswertung;
import de.ivu.elect.business.wahlbeteiligung.entity.WahlbeteiligungVerlauf;
import de.ivu.elect.business.wahlbeteiligung.entity.WahlbeteiligungVerlaufGebiet;
import de.ivu.elect.business.wahlvorschlag.boundary.DirektkandidatFactory;
import de.ivu.elect.business.wahlvorschlag.boundary.ListeFactory;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;

public class ExchangeWahlAufteiler implements WahlAufteiler {

  @Inject
  private transient WahldurchfuehrungsgebietFactory wahldurchfuehrungsgebietFactory;

  @Inject
  private transient GebietUebernehmen gebietUebernehmen;

  @Inject
  private transient GruppeFactory gruppeFactory;

  @Inject
  private transient PolitischeGruppeFactory politischeGruppeFactory;

  @Inject
  private transient GruppeImGebietFactory gruppeImGebietFactory;

  @Inject
  private transient DirektkandidatFactory direktkandidatFactory;

  @Inject
  private transient DirektkandidaturFactory direktkandidaturFactory;

  @Inject
  private transient ListeFactory listeFactory;

  @Inject
  private transient ListenkandidaturFactory listenkandidaturFactory;

  @Inject
  private transient WahlterminFactory wahlterminFactory;

  @Inject
  private transient WahldurchfuehrungFactory wahldurchfuehrungFactory;

  @Inject
  private transient KonfigurationLoader konfigurationLoader;

  @Override
  public StimmergebnisDaten erzeugeStimmergebnisMappedFuerAufgeteiltesGebiet(StimmergebnisDaten stimmergebnisDaten, Wahldurchfuehrungsgebiet aufgeteiltesGebiet) {

    Wahltermin wahlterminExport = wahlterminFactory.create();
    stimmergebnisDaten.getWahl().getWahltermin().copyEntityAttributesUsingSetter(wahlterminExport);
    Wahldurchfuehrung wahlExport = wahldurchfuehrungFactory.create();
    stimmergebnisDaten.getWahl().copyEntityAttributesUsingSetter(wahlExport);

    wahlExport.setWahltermin(wahlterminExport);
    wahlExport.setWahlart(aufgeteiltesGebiet.bestimmeWahlartBeiAufteilung());

    Map<Gruppe, Gruppe> gruppenExportNachPersistent = erzeugeGemappteGruppen(stimmergebnisDaten.getGruppen(), wahlExport);

    Map<Gebiet, Wahldurchfuehrungsgebiet> gebietExportNachPersistent = erzeugeGemappteGebiete(stimmergebnisDaten.getWahl().getMandant(), stimmergebnisDaten.getGebiete(), aufgeteiltesGebiet, wahlExport);

    Map<GruppeImGebiet, GruppeImGebiet> gigExportNachPersistent = erzeugeGemappteGigs(stimmergebnisDaten.getGruppenImGebiet(), gruppenExportNachPersistent,
            gebietExportNachPersistent);

    Map<GruppeImGebietTK, GruppeImGebiet> gigExportNachTk = gigExportNachPersistent.values().stream()
            .collect(toMap(GruppeImGebiet::getGruppeImGebietTK, identity()));

    Map<Personendaten, Personendaten> personendatenExportNachPersistent = new HashMap<>();

    Map<Wahlvorschlag, Wahlvorschlag> wahlvorschlagExportNachPersistent = erzeugeWahlvorschlaege(stimmergebnisDaten, gigExportNachTk, aufgeteiltesGebiet,
            personendatenExportNachPersistent);

    List<Kandidatur> kandidaturen = extrahiereKandidaturen(personendatenExportNachPersistent.values());

    List<PersonenVerknuepfung> personenVerknuepfungen = mappePersonenVerknuepfung(stimmergebnisDaten.getPersonenVerknuepfungen(),
            personendatenExportNachPersistent);

    List<InternetSeite> internetSeiten = /* TODO, falls es hier zukünftig Abhängigkeiten auf Gebiete gibt, diese ersetzen */ stimmergebnisDaten
            .getInternetSeiten();

    List<Gebietsgruppierung> gebietsgruppierungenMapped = erzeugeGemappteGebietsgruppierungen(gebietExportNachPersistent,
            stimmergebnisDaten.getGebietsgruppierungen());

    List<WahlbeteiligungVerlauf> wahlbeteiligungVerlaufs = erzeugeGemappteWahlbeteiligungVerlauf(gebietExportNachPersistent,
            stimmergebnisDaten.getWahlbeteiligungVerlaeufe(), wahlExport);

    List<WahlbeteiligungAuswertung> wahlbeteiligungAuswertungs = erzeugeGemappteWahlbeteiligungAuswertung(gebietExportNachPersistent,
            stimmergebnisDaten.getWahlbeteiligungAuswertungen(), wahlExport);

    List<StimmeingabePlausiKonfiguration> stimmeingabePlausiKonfigurationen = /* TODO, falls es hier zukünftig Abhängigkeiten auf Gebiete gibt, diese ersetzen */ stimmergebnisDaten
            .getStimmeingabePlausiKonfigurationen();

    StimmergebnisDatenStatisch stimmergebnisDatenStatischFuerExport = new StimmergebnisDatenStatisch(stimmergebnisDaten);
    return stimmergebnisDatenStatischFuerExport
            .createStimmergebnisdatenFuerAngepassteGebiete(wahlExport, gruppenExportNachPersistent.values(), gebietExportNachPersistent.values(),
                    gigExportNachPersistent.values(), wahlvorschlagExportNachPersistent.values(), kandidaturen, personenVerknuepfungen,
                    personendatenExportNachPersistent, wahlvorschlagExportNachPersistent,
                    internetSeiten, gebietsgruppierungenMapped, wahlbeteiligungVerlaufs, wahlbeteiligungAuswertungs, stimmeingabePlausiKonfigurationen);
  }

  private List<WahlbeteiligungAuswertung> erzeugeGemappteWahlbeteiligungAuswertung(Map<Gebiet, Wahldurchfuehrungsgebiet> gebietExportNachPersistent,
                                                                                   List<WahlbeteiligungAuswertung> wahlbeteiligungAuswertungen, Wahldurchfuehrung wahlExport) {
    List<WahlbeteiligungAuswertung> result = new ArrayList<>(wahlbeteiligungAuswertungen.size() + 1);

    for (WahlbeteiligungAuswertung from : wahlbeteiligungAuswertungen) {
      WahlbeteiligungAuswertung to = new WahlbeteiligungAuswertung();
      result.add(to);
      to.setWahl(wahlExport);
      from.copyEntityAttributesUsingSetter(to);

      for (Wahlbeteiligung fromWahlbeteiligung : from.getWahlbeteiligungsByWahlbeteiligungAuswertung()) {

        Wahldurchfuehrungsgebiet toGebiet = gebietExportNachPersistent.get(fromWahlbeteiligung.getWahldurchfuehrungsgebiet());
        if (toGebiet != null) {
          Wahlbeteiligung toWahlbeteiligung = new Wahlbeteiligung();
          toWahlbeteiligung.setWahlbeteiligungAuswertung(to);
          toWahlbeteiligung.setWahldurchfuehrungsgebiet(toGebiet);
          fromWahlbeteiligung.copyEntityAttributesUsingSetter(toWahlbeteiligung);
        }
      }

    }
    return result;
  }

  private List<WahlbeteiligungVerlauf> erzeugeGemappteWahlbeteiligungVerlauf(Map<Gebiet, Wahldurchfuehrungsgebiet> gebietExportNachPersistent,
                                                                             List<WahlbeteiligungVerlauf> wahlbeteiligungVerlaeufe, Wahldurchfuehrung wahlExport) {
    List<WahlbeteiligungVerlauf> result = new ArrayList<>(wahlbeteiligungVerlaeufe.size() + 1);

    for (WahlbeteiligungVerlauf from : wahlbeteiligungVerlaeufe) {
      WahlbeteiligungVerlauf to = new WahlbeteiligungVerlauf();
      result.add(to);
      to.setWahl(wahlExport);
      from.copyEntityAttributesUsingSetter(to);

      for (WahlbeteiligungVerlaufGebiet fromWahlbeteiligungVerlaufGebiet : from.getWahlbeteiligungVerlaufGebietsByWahlbeteiligungVerlauf()) {

        Gebiet toGebiet = gebietExportNachPersistent.get(fromWahlbeteiligungVerlaufGebiet.getGebiet());
        if (toGebiet != null) {
          WahlbeteiligungVerlaufGebiet toWahlbeteiligungVerlaufGebiet = new WahlbeteiligungVerlaufGebiet();
          toWahlbeteiligungVerlaufGebiet.setWahlbeteiligungVerlauf(to);
          toWahlbeteiligungVerlaufGebiet.setGebiet(toGebiet);
          fromWahlbeteiligungVerlaufGebiet.copyEntityAttributesUsingSetter(toWahlbeteiligungVerlaufGebiet);
        }
      }

    }
    return result;
  }

  // ELECT-7270
  private List<Gebietsgruppierung> erzeugeGemappteGebietsgruppierungen(Map<Gebiet, Wahldurchfuehrungsgebiet> gebietExportNachPersistent,
                                                                       List<Gebietsgruppierung> gebietsgruppierungen) {
    List<Gebietsgruppierung> result = new ArrayList<>();
    for (Gebietsgruppierung gebietsgruppierungPersistent : gebietsgruppierungen) {
      Gebietsgruppierung gebietsgruppierungExport = new Gebietsgruppierung();
      gebietsgruppierungPersistent.copyEntityAttributesUsingSetter(gebietsgruppierungExport);
      for (Gebiet gebietPersistent : gebietsgruppierungPersistent.getGebiets()) {
        if (gebietExportNachPersistent.containsKey(gebietPersistent)) {
          Wahldurchfuehrungsgebiet gebietExport = gebietExportNachPersistent.get(gebietPersistent);
          gebietsgruppierungExport.setWahl(gebietExport.getWahl());
          gebietsgruppierungExport.addGebiet(gebietExport);
        }
      }
      if (!gebietsgruppierungExport.getGebiets().isEmpty()) {
        result.add(gebietsgruppierungExport);
      }
    }
    return result;
  }

  private List<PersonenVerknuepfung> mappePersonenVerknuepfung(List<PersonenVerknuepfung> personenVerknuepfungen, Map<Personendaten, Personendaten> personendatenExportNachPersistent) {
    List<PersonenVerknuepfung> result = new ArrayList<>();

    for (PersonenVerknuepfung personenVerknuepfungPersistent : personenVerknuepfungen) {
      if (personendatenExportNachPersistent.containsKey(personenVerknuepfungPersistent.getPerson1()) && personendatenExportNachPersistent
              .containsKey(personenVerknuepfungPersistent.getPerson2())) {
        PersonenVerknuepfung personenVerknuepfungExport = new PersonenVerknuepfung();
        personenVerknuepfungPersistent.copyEntityAttributesUsingSetter(personenVerknuepfungExport);
        personenVerknuepfungExport.setPerson1(personendatenExportNachPersistent.get(personenVerknuepfungPersistent.getPerson1()));
        personenVerknuepfungExport.setPerson2(personendatenExportNachPersistent.get(personenVerknuepfungPersistent.getPerson2()));
        result.add(personenVerknuepfungExport);
      }
    }

    return result;
  }

  private List<Kandidatur> extrahiereKandidaturen(Collection<Personendaten> values) {
    return values.stream().filter(p -> p.isInstanceOf(Kandidatur.class)).map(p -> p.castTo(Kandidatur.class).getEntity()).collect(toList());
  }

  private Map<Wahlvorschlag, Wahlvorschlag> erzeugeWahlvorschlaege(StimmergebnisDaten stimmergebnisDaten, Map<GruppeImGebietTK, GruppeImGebiet> gigExportNachTk, Wahldurchfuehrungsgebiet gemeinde,
                                                                   Map<Personendaten, Personendaten> personendatenExportNachPersistent) {

    Map<Wahlvorschlag, Wahlvorschlag> result = new HashMap<>();

    for (Wahlvorschlag wahlvorschlagPersistent : stimmergebnisDaten.getWahlvorschlaege()) {
      if (gemeinde.isInGebietshierarchieVon(wahlvorschlagPersistent.getGebiet())) {

        GruppeImGebiet gigExtern = findeExterneGig(gigExportNachTk, gemeinde, wahlvorschlagPersistent);
        Wahlvorschlag wahlvorschlagExtern = kopiereWahlvorschlag(wahlvorschlagPersistent, personendatenExportNachPersistent, gigExtern);

        result.put(wahlvorschlagPersistent, wahlvorschlagExtern);
      }
    }
    return result;
  }

  private GruppeImGebiet findeExterneGig(Map<GruppeImGebietTK, GruppeImGebiet> gigExportNachTk, Wahldurchfuehrungsgebiet gemeinde, Wahlvorschlag wahlvorschlagPersistent) {
    GruppeImGebiet gigExtern = gigExportNachTk.get(wahlvorschlagPersistent.getGruppeImGebiet().getGruppeImGebietTK());
    if (gigExtern != null) {
      return gigExtern;
    }

    GruppeImGebietTK key = new GruppeImGebietTK(gemeinde.getGebietTK(), wahlvorschlagPersistent.getGruppe().getGruppeTK());
    gigExtern = gigExportNachTk.get(key);
    if (gigExtern == null) {
      throw new IllegalStateException("Keine GIG gefunden: " + key + ", habe: " + gigExportNachTk);
    }

    return gigExtern;
  }

  private Wahlvorschlag kopiereWahlvorschlag(Wahlvorschlag wahlvorschlagPersistent, Map<Personendaten, Personendaten> personendatenExportNachPersistent, GruppeImGebiet gigExtern) {

    Wahlvorschlag wahlvorschlagExtern;
    if (wahlvorschlagPersistent.isDirektkandidat()) {
      Direktkandidat direktkandidatPersistent = wahlvorschlagPersistent.castTo(Direktkandidat.class).getEntity();
      Direktkandidat direktkandidatExtern = direktkandidatFactory.create();
      Direktkandidatur direktkandidaturExtern = direktkandidaturFactory.create();
      direktkandidatExtern.setDirektkandidatur(direktkandidaturExtern);
      kopierePersonendaten(direktkandidatPersistent.getDirektkandidatur(), direktkandidaturExtern.getDirektkandidatur(), personendatenExportNachPersistent);
      wahlvorschlagExtern = direktkandidatExtern;
    } else if (wahlvorschlagPersistent.isListe()) {
      Liste listePersistent = wahlvorschlagPersistent.castTo(Liste.class).getEntity();
      Liste listeExtern = listeFactory.create();
      listePersistent.copyEntityAttributesUsingSetter(listeExtern);

      for (Listenkandidatur listenkandidaturPersistent : listePersistent.getListenkandidaturen()) {
        Listenkandidatur listenkandidaturExtern = listenkandidaturFactory.create();
        listenkandidaturExtern.setListe(listeExtern);
        kopierePersonendaten(listenkandidaturPersistent, listenkandidaturExtern, personendatenExportNachPersistent);
      }

      wahlvorschlagExtern = listeExtern;
    } else {
      throw new IllegalStateException("Nicht unterstützter Wahlvorschlag: " + wahlvorschlagPersistent);
    }

    wahlvorschlagExtern.setGruppeImGebiet(gigExtern);

    wahlvorschlagPersistent.copyEntityAttributesUsingSetter(wahlvorschlagExtern);

    return wahlvorschlagExtern;

  }

  protected void kopierePersonendaten(Personendaten von, Personendaten nach, Map<Personendaten, Personendaten> personendatenExportNachPersistent) {
    von.copyEntityAttributesUsingSetter(nach);
    von.getAnschrift().copyEntityAttributesUsingSetter(nach.getAnschrift());
    personendatenExportNachPersistent.put(von, nach);
  }

  private Map<GruppeImGebiet, GruppeImGebiet> erzeugeGemappteGigs(List<GruppeImGebiet> gruppenImGebiet, Map<Gruppe, Gruppe> gruppenExportNachPersistent,
                                                                  Map<Gebiet, Wahldurchfuehrungsgebiet> gebietExportNachPersistent) {
    Map<GruppeImGebiet, GruppeImGebiet> result = new HashMap<>();
    for (GruppeImGebiet gigPersistent : gruppenImGebiet) {
      if (gruppenExportNachPersistent.containsKey(gigPersistent.getGruppe()) && gebietExportNachPersistent.containsKey(gigPersistent.getGebiet())) {
        GruppeImGebiet gigExport = gruppeImGebietFactory.create();
        gigPersistent.copyEntityAttributesUsingSetter(gigExport);
        gigExport.setGruppe(gruppenExportNachPersistent.get(gigPersistent.getGruppe()));
        gigExport.setGebiet(gebietExportNachPersistent.get(gigPersistent.getGebiet()));
        result.put(gigPersistent, gigExport);
      }
    }

    return result;
  }

  private Map<Gruppe, Gruppe> erzeugeGemappteGruppen(List<Gruppe> gruppen, Wahldurchfuehrung wahlExport) {

    Map<Gruppe, Gruppe> result = new HashMap<>();
    for (Gruppe gruppePersistent : gruppen) {
      Gruppe gruppeExport;
      if (gruppePersistent.isPolitischeGruppe()) {
        gruppeExport = politischeGruppeFactory.create();
      } else {
        gruppeExport = gruppeFactory.create();
      }
      gruppePersistent.copyEntityAttributesUsingSetter(gruppeExport);
      gruppeExport.setWahl(wahlExport);

      result.put(gruppePersistent, gruppeExport);

    }
    return result;
  }

  private Map<Gebiet, Wahldurchfuehrungsgebiet> erzeugeGemappteGebiete(Mandant quellMandant, List<Wahldurchfuehrungsgebiet> gebiete, Wahldurchfuehrungsgebiet aufgeteiltesGebiet, Wahldurchfuehrung wahlExport) {
    Map<Gebiet, Wahldurchfuehrungsgebiet> result = new HashMap<>();

    List<Wahldurchfuehrungsgebiet> gebieteInDb = new ArrayList<>(gebiete);
    gebieteInDb.sort(new GebietByBreadthFirstComparator()); // uebergeordnete Gebiete zuerst uebernehmen

    Map<GebietTK, Wahldurchfuehrungsgebiet> wahldurchfuehrungsgebietExportPerTk = new HashMap<>();

    //ELECTKOM-667 vs  ELECT-8549
    boolean rollenUebernehmen = konfigurationLoader.resolveBooleanValue(quellMandant, MandantKonfigurationWerte.WAHL_AUF_MANDANT_AUFTEILEN_GEBIETSRECHTE_UEBERNEHMEN);

    for (Wahldurchfuehrungsgebiet wahldurchfuehrungsgebietInDb : gebieteInDb) {

      if (wahldurchfuehrungsgebietInDb.isEqualOderUntergebietVon(aufgeteiltesGebiet)) {
        Wahldurchfuehrungsgebiet wahldurchfuehrungsgebietExport = wahldurchfuehrungsgebietFactory.create();
        wahldurchfuehrungsgebietExport.setWahl(wahlExport);

        GebietUebernehmenContext uebernehmenContext = new GebietUebernehmenContext(true /* Für WES-Export? */, true, rollenUebernehmen, true/*legacy*/, true/*legacy*/);
        gebietUebernehmen.kopierereGebietUnveraendert(wahldurchfuehrungsgebietInDb, wahldurchfuehrungsgebietExport, uebernehmenContext);
        wahldurchfuehrungsgebietExport.setGebietsart(wahldurchfuehrungsgebietInDb.getGebietsart());

        wahldurchfuehrungsgebietExportPerTk.put(wahldurchfuehrungsgebietInDb.getGebietTK(), wahldurchfuehrungsgebietExport);

        Gebiet uebergeordnetesGebietInDb = wahldurchfuehrungsgebietInDb.getUebergeordnetesGebiet();

        if (uebergeordnetesGebietInDb != null) {
          wahldurchfuehrungsgebietExport.setUebergeordnetesGebiet(wahldurchfuehrungsgebietExportPerTk.get(uebergeordnetesGebietInDb.getGebietTK()));
        }

        // ELECT-9076
        if (wahldurchfuehrungsgebietInDb.equals(aufgeteiltesGebiet)) {
          // wenn neues Wurzelgebiet, dann Sitze und Stimmen von übergeordnetem Gebiet nehmen, wenn noch nicht vorhanden
          if (wahldurchfuehrungsgebietExport.getAnzahlSitze() == null) {
            wahldurchfuehrungsgebietExport.setAnzahlSitze(bestimmeAnzahlSitzeAusUebergeordnetemGebiet(wahldurchfuehrungsgebietInDb));
          }
          if (wahldurchfuehrungsgebietExport.getAnzahlStimmenProWaehler() == null) {
            wahldurchfuehrungsgebietExport.setAnzahlStimmenProWaehler(bestimmeAnzahlStimmenProWaehlerAusUebergeordnetemGebiet(wahldurchfuehrungsgebietInDb));
          }
        }

        result.put(wahldurchfuehrungsgebietInDb, wahldurchfuehrungsgebietExport);
      }
    }

    return result;
  }

  @Nullable
  private Long bestimmeAnzahlSitzeAusUebergeordnetemGebiet(Gebiet gebiet) {
    if (gebiet == null) {
      return null;
    }
    if (gebiet.getAnzahlSitze() != null) {
      return gebiet.getAnzahlSitze();
    }
    return bestimmeAnzahlSitzeAusUebergeordnetemGebiet(gebiet.getUebergeordnetesGebiet());

  }

  @Nullable
  private Long bestimmeAnzahlStimmenProWaehlerAusUebergeordnetemGebiet(Gebiet gebiet) {
    if (gebiet == null) {
      return null;
    }
    if (gebiet.getAnzahlStimmenProWaehler() != null) {
      return gebiet.getAnzahlStimmenProWaehler();
    }
    return bestimmeAnzahlStimmenProWaehlerAusUebergeordnetemGebiet(gebiet.getUebergeordnetesGebiet());

  }
}
