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

import static de.ivu.elect.jee.entity.EntityUtil.castTo;
import static java.util.stream.Collectors.toSet;

import java.util.Collection;

import javax.annotation.Nullable;

import de.ivu.elect.business.ergebnis.control.StimmergebnisDaten;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.kandidatur.boundary.WasWaehlerBenannteKandidaturKonfiguration;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.sitzberechnung.control.util.SitzberechnungLogger;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.jee.faces.Messages;

public abstract class AbstractListenwahlMehrheitswahlPruefer {

  private final WasWaehlerBenannteKandidaturKonfiguration waehlerBenannteKandidaturKonfiguration;

  private final StimmergebnisDaten stimmergebnisDaten;

  public AbstractListenwahlMehrheitswahlPruefer(WasWaehlerBenannteKandidaturKonfiguration waehlerBenannteKandidaturKonfiguration, StimmergebnisDaten stimmergebnisDaten) {
    super();

    this.waehlerBenannteKandidaturKonfiguration = waehlerBenannteKandidaturKonfiguration;

    this.stimmergebnisDaten = stimmergebnisDaten;
  }

  public boolean isWaehlerBenannteListe(Liste liste) {
    return waehlerBenannteKandidaturKonfiguration.isWaehlerBenannteListe(liste);
  }

  public boolean isWaehlerBenannteListenkandidatur(Kandidatur kandidatur) {
    return waehlerBenannteKandidaturKonfiguration.isWaehlerBenannteListenkandidatur(kandidatur);
  }

  public boolean isWaehlerBenannteListenkandidaturSonstige(Messages messages, Kandidatur kandidatur) {
    return waehlerBenannteKandidaturKonfiguration.isWaehlerBenannteListenkandidaturSonstige(messages, kandidatur);
  }

  public boolean isMehrheitswahl(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, SitzberechnungLogger logger) {
    if (stimmergebnisDaten != null) {
      return isMehrheitswahl(wahldurchfuehrungsgebiet, stimmergebnisDaten.getListenZuGebiet(wahldurchfuehrungsgebiet), logger);
    }

    throw new IllegalStateException("Stimmergebnisdaten wurden nicht initialisiert!");
  }

  public boolean isMehrheitswahl(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, Collection< ? extends Wahlvorschlag> wahlvorschlaege) {
    return isMehrheitswahl(wahldurchfuehrungsgebiet, wahlvorschlaege.stream().filter(Wahlvorschlag::isListe).map(wahlvorschlag -> castTo(wahlvorschlag, Liste.class)).collect(toSet()), null);
  }

  // ELECTKOM-616
  public abstract boolean isMehrheitswahl(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, Collection<Liste> listen, @Nullable SitzberechnungLogger logger);

  protected long countListenAufStimmzettelWaehlerBenannteListenExcluded(Collection<Liste> listen) {
    int result = 0;

    for (Liste liste : listen) {
      if (liste.isAufStimmzettel() && !isWaehlerBenannteListe(liste)) {
        result++;
      }
    }

    return result;
  }

  protected long countListenkandidaturenAufStimmzettel(Collection<Liste> listen) {
    long result = 0L;

    for (Liste liste : listen) {
      if (liste.isAufStimmzettel()) {
        for (Listenkandidatur listenkandidatur : liste.getListenkandidaturen()) {
          if (listenkandidatur.isAufStimmzettel()) {
            result++;
          }
        }
      }
    }

    return result;
  }
}
