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.Ergebnis;
import de.ivu.elect.business.ergebnis.entity.Ergebnisart;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.WahlPK;
import org.apache.commons.lang3.tuple.Pair;

/**
 * HINT: Performanceoptimierung, Ergebnisdaten je Wahl+Ergebnisart nur einmal laden
 */
public class ErgebnisDatenHolder {

  private final Map<Pair<WahlPK, Ergebnisart>, ErgebnisDaten> ergebnisDatenMap = new HashMap<>();
  private final ErgebnisDatenCreator ergebnisDatenCreator;

  public ErgebnisDatenHolder(ErgebnisDatenCreator ergebnisDatenCreator) {
    this.ergebnisDatenCreator = ergebnisDatenCreator;
  }

  public void reset() {
    ergebnisDatenMap.clear();
  }

  public ErgebnisDaten getErgebnisDaten(Wahl wahl, Ergebnisart ergebnisart) {
    return ergebnisDatenMap.computeIfAbsent(Pair.of(wahl.getPk(), ergebnisart), (key) -> createErgebnisDatenFuerWahlUndErgebnisart(wahl, ergebnisart));
  }

  private ErgebnisDaten createErgebnisDatenFuerWahlUndErgebnisart(Wahl wahl, Ergebnisart ergebnisart) {
    Ergebnis ergebnis = findErgebnis(wahl, ergebnisart);
    return ergebnisDatenCreator.createErgebnisDatenSitzberechnung(ergebnis);
  }

  private Ergebnis findErgebnis(Wahl wahl, Ergebnisart ergebnisart) {
    List<Ergebnis> ergebnisse = ergebnisDatenCreator.getErgebnisDAO().findByWahlAndErgebnisart(wahl, ergebnisart);

    if (ergebnisse.size() == 1) {
      return ergebnisse.get(0);
    }

    throw new IllegalStateException("Genau ein ergebnis mit ergebnisart " + ergebnisart.name() + " erwartet, aber "
        + ergebnisse.size() + " gefunden!");
  }
}
