
package de.ivu.elect.sitzberechnung.verteilung.niemeyer;

import static java.util.Collections.emptyList;

import java.util.ArrayList;
import java.util.List;

import de.ivu.elect.sitzberechnung.math.Fraction;
import de.ivu.elect.sitzberechnung.verteilung.AbstractVerteilungErgebnis;
import de.ivu.elect.sitzberechnung.verteilung.Teilnehmer;
import de.ivu.elect.sitzberechnung.verteilung.VerteilungContext;

/**
 * Das Ergebnis einer Sitzverteilung nach Hare-Niemeyer. Man erhält es nach Verteilung der abgerundeten Sitze und der Restsitze von einer {@link HareNiemeyerVerteilung}. Durch eine evtl. spätere
 * Verteilung nach Los (oder anderen Kriterien) werden nachträglich noch Sitze vergeben und damit dieses Objekt modifiziert. Es enthält für jeden Teilnehmer an der Verteilung ein
 * {@link HareNiemeyerTeilnehmerErgebnis}, das ebenfalls noch durch spätere Verteilung nach Los (oder anderen Kriterien) modifiziert werden kann.
 */
public class HareNiemeyerErgebnis extends AbstractVerteilungErgebnis<HareNiemeyerTeilnehmerErgebnis> {

  /**
   * Ergebnis der HareNiemeyerErgebnis ohne dass ein Losverfahren nötig war
   */
  public HareNiemeyerErgebnis(VerteilungContext context, List<HareNiemeyerTeilnehmerErgebnis> teilnehmerErgebnisse) {
    this(context, teilnehmerErgebnisse, 0L, emptyList());
  }

  public HareNiemeyerErgebnis(VerteilungContext context, List<HareNiemeyerTeilnehmerErgebnis> teilnehmerErgebnisse, long anzahlSitzeZuVerlosen,
      List<HareNiemeyerTeilnehmerErgebnis> teilnehmerErgebnisseImLosverfahren) {
    super(context, teilnehmerErgebnisse, anzahlSitzeZuVerlosen, teilnehmerErgebnisseImLosverfahren);
  }

  /**
   * @return der Rest, mit dem der letzte Restsitz zugeteilt wurde. null, wenn kein Restsitz zugeteilt wurde.
   */
  public Fraction getLetzterRest() {
    Fraction min = null;

    for (HareNiemeyerTeilnehmerErgebnis teilnehmerErgebnis : getTeilnehmerErgebnisse()) {
      if (teilnehmerErgebnis.getRestsitze() > 0L) {
        Fraction rest = teilnehmerErgebnis.getRest(getFractionConverter());

        if (min == null || min.compareTo(rest) > 0) {
          min = rest;
        }
      }
    }

    return min;
  }

  /**
   * @return Ergebnis der Verteilung, wenn keine richtige Verteilung stattgefunden hat
   */
  public static HareNiemeyerErgebnis ohneVerteilung(VerteilungContext context, List< ? extends Teilnehmer> teilnehmerInVerteilung) {
    List<HareNiemeyerTeilnehmerErgebnis> teilnehmerErgebnisse = new ArrayList<>();

    for (Teilnehmer teilnehmer : teilnehmerInVerteilung) {
      teilnehmerErgebnisse.add(HareNiemeyerTeilnehmerErgebnis.ohneVerteilung(teilnehmer));
    }

    return new HareNiemeyerErgebnis(context, teilnehmerErgebnisse);
  }
}
