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

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

import de.ivu.elect.business.ergebnis.entity.Stimmabgabeart;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.entity.PolitischeGruppe;
import de.ivu.elect.business.internet.control.GebietUndStimmabgabeart;

public class ErgebnisDatenGesamtstimmen extends AbstractErgebnisDaten {

  private final StimmergebnisDaten stimmergebnisDaten;

  private final Map<GebietUndStimmabgabeart, Map<PolitischeGruppe, Long>> gesamtStimmenAktuell = new HashMap<>();

  public ErgebnisDatenGesamtstimmen(StimmergebnisDaten stimmergebnisDaten) {
    super(stimmergebnisDaten::getUntergeordneteGebiete, stimmergebnisDaten::getErfassteGebiete);
    this.stimmergebnisDaten = stimmergebnisDaten;
  }

  public Long getGesamtstimmenAktuell(PolitischeGruppe politischeGruppe, Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return notNull(getGesamtStimmenAktuell(new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, Stimmabgabeart.GESAMT)).get(politischeGruppe));
  }

  public Map<PolitischeGruppe, Long> getGesamtstimmenAktuell(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return getGesamtStimmenAktuell(new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, Stimmabgabeart.GESAMT));
  }

  public Map<PolitischeGruppe, Long> getGesamtStimmenAktuell(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, Stimmabgabeart stimmabgabeart) {
    return getGesamtStimmenAktuell(new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, stimmabgabeart));
  }

  public Map<PolitischeGruppe, Long> getGesamtStimmenAktuell(GebietUndStimmabgabeart gebietUndStimmabgabeart) {
    Map<PolitischeGruppe, Long> result = gesamtStimmenAktuell.get(gebietUndStimmabgabeart);
    if (result == null) {
      result = new HashMap<>();
      summiereErstUndZweitstimmen(stimmergebnisDaten.getErststimmenAktuell(gebietUndStimmabgabeart), stimmergebnisDaten.getZweitstimmenAktuell(gebietUndStimmabgabeart), result,
          stimmergebnisDaten.getPolitischeGruppenSortiertNachPositionAufGebiet(gebietUndStimmabgabeart.getWahldurchfuehrungsgebiet()));
      gesamtStimmenAktuell.put(gebietUndStimmabgabeart, result);
    }
    return result;
  }

  public Long getGesamtStimmenAktuell(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, PolitischeGruppe politischeGruppe, Stimmabgabeart stimmabgabeart) {
    return notNull(getGesamtStimmenAktuell(new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, stimmabgabeart)).get(politischeGruppe));
  }

  public Long getGesamtstimmenVorperiode(PolitischeGruppe politischeGruppe, Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return notNull(getGesamtStimmenVorperiode(new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, Stimmabgabeart.GESAMT)).get(politischeGruppe));
  }

  public Map<PolitischeGruppe, Long> getGesamtstimmenVorperiode(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return getGesamtStimmenVorperiode(new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, Stimmabgabeart.GESAMT));
  }

  private final Map<GebietUndStimmabgabeart, Map<PolitischeGruppe, Long>> gesamtStimmenVorperiode = new HashMap<>();

  public Map<PolitischeGruppe, Long> getGesamtStimmenVorperiode(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, Stimmabgabeart stimmabgabeart) {
    return getGesamtStimmenVorperiode(new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, stimmabgabeart));
  }

  public Map<PolitischeGruppe, Long> getGesamtStimmenVorperiode(GebietUndStimmabgabeart gebietUndStimmabgabeart) {
    Map<PolitischeGruppe, Long> result = gesamtStimmenVorperiode.get(gebietUndStimmabgabeart);
    if (result == null) {
      result = new HashMap<>();
      summiereErstUndZweitstimmen(stimmergebnisDaten.getErststimmenVorperiode(gebietUndStimmabgabeart), stimmergebnisDaten.getZweitstimmenVorperiode(gebietUndStimmabgabeart), result,
          stimmergebnisDaten.getPolitischeGruppenSortiertNachPositionAufGebiet(gebietUndStimmabgabeart.getWahldurchfuehrungsgebiet()));
      gesamtStimmenVorperiode.put(gebietUndStimmabgabeart, result);

    }
    return result;
  }

  private final Map<GebietUndStimmabgabeart, Long> gesamtStimmenGueltigeVorperiode = new HashMap<>();

  /**
   * @deprecated ELECT-8887
   * @see ErgebnisDatenGueltige#getSummeGesamtstimmenVorperiodeGueltig
   */
  @Deprecated
  public Long getGesamtStimmenGueltigeVorperiode(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, Stimmabgabeart stimmabgabeart) {
    return getGesamtStimmenGueltigeVorperiode(new GebietUndStimmabgabeart(wahldurchfuehrungsgebiet, stimmabgabeart));
  }

  /**
   * @deprecated ELECT-8887
   * @see ErgebnisDatenGueltige#getSummeGesamtstimmenVorperiodeGueltig
   */
  @Deprecated
  public Long getGesamtStimmenGueltigeVorperiode(GebietUndStimmabgabeart gebietUndStimmabgabeart) {
    Long result = gesamtStimmenGueltigeVorperiode.get(gebietUndStimmabgabeart);
    if (result == null) {
      Long erststimmenVorperiodeGueltige = stimmergebnisDaten.getErststimmenVorperiodeGueltige(gebietUndStimmabgabeart);
      Long zweitstimmenVorperiodeGueltige = stimmergebnisDaten.getZweitstimmenVorperiodeGueltige(gebietUndStimmabgabeart);

      if (erststimmenVorperiodeGueltige != null && zweitstimmenVorperiodeGueltige != null) {
        result = erststimmenVorperiodeGueltige + zweitstimmenVorperiodeGueltige;
      } else {
        if (erststimmenVorperiodeGueltige != null) {
          result = erststimmenVorperiodeGueltige;
        }
        if (zweitstimmenVorperiodeGueltige != null) {
          result = zweitstimmenVorperiodeGueltige;
        }

      }
      gesamtStimmenGueltigeVorperiode.put(gebietUndStimmabgabeart, result);
    }
    return result;
  }

  private void summiereErstUndZweitstimmen(Map<PolitischeGruppe, Long> erststimmenAktuellLokal, Map<PolitischeGruppe, Long> zweitstimmenAktuellLokal, Map<PolitischeGruppe, Long> summenMap,
      List<PolitischeGruppe> politischeGruppenSortiertNachPositionAufGebiet) {
    for (PolitischeGruppe politischeGruppe : politischeGruppenSortiertNachPositionAufGebiet) {
      Long stimmen = 0L;
      Long erststimmen = erststimmenAktuellLokal.get(politischeGruppe);
      if (erststimmen != null) {
        stimmen += erststimmen;
      }
      Long zweitstimmen = zweitstimmenAktuellLokal.get(politischeGruppe);
      if (zweitstimmen != null) {
        stimmen += zweitstimmen;
      }
      summenMap.put(politischeGruppe, stimmen);
    }
  }
}
