
package de.ivu.elect.sitzberechnung.verteilung;

import java.util.List;

import de.ivu.elect.sitzberechnung.math.FractionConverter;

public abstract class AbstractVerteilung<E extends TeilnehmerErgebnis, V extends AbstractVerteilungErgebnis<E>> {

  private final FractionConverter fractionConverter;

  protected AbstractVerteilung(FractionConverter fractionConverter) {
    super();

    this.fractionConverter = fractionConverter;
  }

  public V verteileSitze(long anzahlSitze, List< ? extends Teilnehmer> teilnehmerInVerteilung) {
    VerteilungContext context = new VerteilungContext(fractionConverter, anzahlSitze, teilnehmerInVerteilung);

    if (context.getAnzahlSitze() == 0) {
      return verteileSitzeKeineSitze(context, teilnehmerInVerteilung);
    }

    if (context.getAnzahlStimmenGesamt() == 0) {
      return verteileSitzeKeineStimmen(context, teilnehmerInVerteilung);
    }

    return verteileSitze(context, teilnehmerInVerteilung);
  }

  /**
   * @param anzahlSitze
   *          Anzahl zu verteilender Sitze (> 0)
   * @param teilnehmerInVerteilung
   * @param anzahlStimmenGesamt
   *          Summe der Stimmen aller Teilnehmer (> 0)
   *
   * @return
   */
  protected abstract V verteileSitze(VerteilungContext context, List< ? extends Teilnehmer> teilnehmerInVerteilung);

  /**
   * @param teilnehmerInVerteilung
   *
   * @return Ergebnis einer Verteilung, wenn keine Sitze zu verteilen sind.
   */
  protected abstract V verteileSitzeKeineSitze(VerteilungContext context, List< ? extends Teilnehmer> teilnehmerInVerteilung);

  /**
   * @param anzahlSitze
   *          Anzahl zu verteilender Sitze (> 0)
   * @param teilnehmerInVerteilung
   *
   * @return Ergebnis einer Verteilung, wenn kein Teilnehmer eine Stimme erhalten hat.
   */
  protected abstract V verteileSitzeKeineStimmen(VerteilungContext context, List< ? extends Teilnehmer> teilnehmerInVerteilung);
}
