package de.ivu.elect.business.hochrechnung.entity;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;

public class StimmenhochrechnerAusgabedaten {
  private final HochrechneralgorithmusAusfuehrbarkeitStatus ausfuehrbarkeitStatus;
  private final Map<Gebiet, StimmenhochrechnerGebietAusgabedaten> ausgabedatenProGebiet = new HashMap<>();

  public StimmenhochrechnerAusgabedaten(HochrechneralgorithmusAusfuehrbarkeitStatus ausfuehrbarkeitStatus) {
    this.ausfuehrbarkeitStatus = ausfuehrbarkeitStatus;
  }

  public HochrechneralgorithmusAusfuehrbarkeitStatus getAusfuehrbarkeitStatus() {
    return ausfuehrbarkeitStatus;
  }

  public void initializeAusgabedaten(StimmenHochrechnerEingabedaten<Long> eingabedaten, KoordinatenInformationen koordinatenInformationen) {
    ausgabedatenProGebiet.clear();
    fuelleInformationenAusVorperiode (eingabedaten, koordinatenInformationen);
    fuelleInformationenAusAktuellerWahl (eingabedaten, koordinatenInformationen);
  }

  public Map<Gebiet, StimmenhochrechnerGebietAusgabedaten> getAusgabedatenProGebiet() {
    return ausgabedatenProGebiet;
  }

  public StimmenhochrechnerGebietAusgabedaten getAusgabedatenVomGebiet(Gebiet gebiet) {
    return ausgabedatenProGebiet.get(gebiet);
  }

  private void fuelleInformationenAusVorperiode(StimmenHochrechnerEingabedaten<Long> eingabedaten, KoordinatenInformationen koordinatenInformationen) {
    fuelleVorhandeneInformationen (eingabedaten.getVorperiode(), StimmenhochrechnerGebietAusgabedaten::setVorperiodeAnteile, StimmenhochrechnerGebietAusgabedaten::setVorperiodeAnzahlen, koordinatenInformationen);
  }

  private void fuelleInformationenAusAktuellerWahl(StimmenHochrechnerEingabedaten<Long> eingabedaten, KoordinatenInformationen koordinatenInformationen) {
    fuelleVorhandeneInformationen (eingabedaten.getAktuelleWahl(), StimmenhochrechnerGebietAusgabedaten::setAktuellAnteile, StimmenhochrechnerGebietAusgabedaten::setAktuellAnzahlen, koordinatenInformationen);
  }

  private void fuelleVorhandeneInformationen(Map<Gebiet, GebietDaten<Long>> ergebnisse,
                                             BiConsumer<StimmenhochrechnerGebietAusgabedaten,GebietDaten<Double>> setAlsAnteile,
                                             BiConsumer<StimmenhochrechnerGebietAusgabedaten, GebietDaten<Long>> setAlsZahlen, KoordinatenInformationen koordinatenInformationen) {
    ergebnisse.entrySet().forEach(
        entry ->  fuelleVorhandeneInformationen(entry, setAlsAnteile, setAlsZahlen, koordinatenInformationen)
    );
  }

  private void fuelleVorhandeneInformationen(Map.Entry<Gebiet, GebietDaten<Long>> gebietDaten,
                                             BiConsumer<StimmenhochrechnerGebietAusgabedaten,GebietDaten<Double>> setAlsAnteile,
                                             BiConsumer<StimmenhochrechnerGebietAusgabedaten, GebietDaten<Long>> setAlsZahlen,
                                             KoordinatenInformationen koordinatenInformationen) {
    StimmenhochrechnerGebietAusgabedaten gebietAusgabedaten = ausgabedatenProGebiet.get(gebietDaten.getKey());
    if (gebietAusgabedaten == null) {
      gebietAusgabedaten = new StimmenhochrechnerGebietAusgabedaten(gebietDaten.getKey(), koordinatenInformationen);
    }
    ausgabedatenProGebiet.put(gebietDaten.getKey(), gebietAusgabedaten);

    setAlsZahlen.accept(gebietAusgabedaten, gebietDaten.getValue());
    GebietDaten<Double> gebietDatenAlsAnteile = new GebietDatenMitStimmenAnteilen(gebietDaten.getValue());
    setAlsAnteile.accept(gebietAusgabedaten, gebietDatenAlsAnteile);
  }
}
