
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 java.util.Set;

import javax.annotation.Nullable;

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;

  protected AbstractListenwahlMehrheitswahlPruefer(WasWaehlerBenannteKandidaturKonfiguration waehlerBenannteKandidaturKonfiguration) {
    super();

    this.waehlerBenannteKandidaturKonfiguration = waehlerBenannteKandidaturKonfiguration;
  }

  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, Collection< ? extends Wahlvorschlag> wahlvorschlaege) {
    Set<Liste> listen = wahlvorschlaege.stream() //
        .filter(Wahlvorschlag::isListe) //
        .map(wahlvorschlag -> castTo(wahlvorschlag, Liste.class)) //
        .filter(liste -> liste.getGebiet().isInGebietshierarchieUebergeordnetesGebietVon(wahldurchfuehrungsgebiet)) //
        .collect(toSet());

    return isMehrheitswahl(wahldurchfuehrungsgebiet, listen, 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;
  }
}
