
package de.ivu.elect.business.sitzberechnung.control.saintelague;

import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.stream.Collectors;

import de.ivu.elect.business.sitzberechnung.control.util.Fraction;
import de.ivu.elect.business.sitzberechnung.control.util.NachNummerSortierer;

public class SainteLagueHoechstzahlSortierer {

  private final NachNummerSortierer<SainteLagueHoechstzahl, Fraction> sortierer;

  private final List<SainteLagueHoechstzahl> vordere;

  private final SortedMap<Fraction, List<SainteLagueHoechstzahl>> vordereGruppiert;

  private final List<SainteLagueHoechstzahl> unentschiedene;

  private final SortedMap<Fraction, List<SainteLagueHoechstzahl>> unentschiedeneGruppiert;

  private final List<SainteLagueHoechstzahl> hintere;

  private final SortedMap<Fraction, List<SainteLagueHoechstzahl>> hintereGruppiert;

  public SainteLagueHoechstzahlSortierer(long anzahlSitzeGesamt, List<SainteLagueHoechstzahl> hoechstzahlen) {
    super();

    this.sortierer = new NachNummerSortierer<>((int) anzahlSitzeGesamt);
    hoechstzahlen.forEach(hoechstzahl -> this.sortierer.add(hoechstzahl.getFraction(), hoechstzahl));

    this.vordere = sortierer.getVordere();
    this.vordereGruppiert = sortierer.getVordereGruppiert();

    this.unentschiedene = sortierer.getUnentschiedene();
    this.unentschiedeneGruppiert = sortierer.getUnentschiedeneGruppiert();

    this.hintere = sortierer.getHintere();
    this.hintereGruppiert = sortierer.getHintereGruppiert();
  }

  public boolean isEntschieden() {
    return sortierer.isEntschieden();
  }

  public long getAnzahlSitzeGesamt() {
    return sortierer.getAnzahlSitze();
  }

  public long getAnzahlSitzeEntschieden() {
    return getHoechstzahlenMitSitzenEntschiedenPerTeilnehmerErgebnis().values().stream().mapToLong(List::size).sum();
  }

  public Map<SainteLagueTeilnehmerErgebnis, List<SainteLagueHoechstzahl>> getHoechstzahlenMitSitzenEntschiedenPerTeilnehmerErgebnis() {
    return getHoechstzahlenMitSitzenEntschieden().stream().collect(Collectors.groupingBy(SainteLagueHoechstzahl::getTeilnehmerErgebnis));
  }

  public SortedMap<Fraction, List<SainteLagueHoechstzahl>> getHoechstzahlenMitSitzenEntschiedenPerFraction() {
    return vordereGruppiert;
  }

  private List<SainteLagueHoechstzahl> getHoechstzahlenMitSitzenEntschieden() {
    return vordere;
  }

  public long getAnzahlSitzeUnentschieden() {
    return Math.max(0, getAnzahlSitzeGesamt() - getAnzahlSitzeEntschieden());
  }

  public Map<SainteLagueTeilnehmerErgebnis, List<SainteLagueHoechstzahl>> getHoechstzahlenMitSitzenUnentschiedenPerTeilnehmerErgebnis() {
    return getHoechstzahlenMitSitzenUnentschieden().stream().collect(Collectors.groupingBy(SainteLagueHoechstzahl::getTeilnehmerErgebnis));
  }

  public SortedMap<Fraction, List<SainteLagueHoechstzahl>> getHoechstzahlenMitSitzenUnentschiedenPerFraction() {
    return unentschiedeneGruppiert;
  }

  private List<SainteLagueHoechstzahl> getHoechstzahlenMitSitzenUnentschieden() {
    return unentschiedene;
  }

  public Map<SainteLagueTeilnehmerErgebnis, List<SainteLagueHoechstzahl>> getHoechstzahlenOhneSitzPerTeilnehmerErgebnis() {
    return getHoechstzahlenOhneSitz().stream().collect(Collectors.groupingBy(SainteLagueHoechstzahl::getTeilnehmerErgebnis));
  }

  public SortedMap<Fraction, List<SainteLagueHoechstzahl>> getHoechstzahlenOhneSitzPerFraction() {
    return hintereGruppiert;
  }

  private List<SainteLagueHoechstzahl> getHoechstzahlenOhneSitz() {
    return hintere;
  }
}
