
package de.ivu.elect.business.wahlvorschlag.boundary;

import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import javax.ejb.Stateless;
import javax.inject.Inject;

import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturDAO;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.pruefung.boundary.ZulassungPruefer;
import de.ivu.elect.business.pruefung.boundary.ZulassungPrueferDAOFactory;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;

@Stateless
public class WahlvorschlagStatusuebersicht {

  @Inject
  private transient WahlvorschlagDAO wahlvorschlagDAO;

  @Inject
  private transient ListenkandidaturDAO listenkandidaturDAO;

  @Inject
  private transient GebietDAO gebietDAO;

  @Inject
  private transient ZulassungPrueferDAOFactory zulassungPrueferDAOFactory;

  public WahlvorschlagStatusuebersicht() {
    super();
  }

  public Map<WahlvorschlagStatusFuerStatusuebersicht, Long> getAnzahlWahlvorschlaegeProStatus(Wahl wahlNotAttached, Gebiet gebietNotAttached) {
    return getAnzahlWahlvorschlaegeProStatus(wahlNotAttached, gebietNotAttached, x -> true);
  }

  public Map<WahlvorschlagStatusFuerStatusuebersicht, Long> getAnzahlWahlvorschlaegeProStatus(Wahl wahlNotAttached, Gebiet gebietNotAttached, Predicate<Wahlvorschlag> filter) {

    if (wahlNotAttached == null || gebietNotAttached == null) {
      return Collections.emptyMap();
    }

    Gebiet gebiet = gebietDAO.attach(gebietNotAttached);
    Map<WahlvorschlagStatusFuerStatusuebersicht, Long> result = new EnumMap<>(WahlvorschlagStatusFuerStatusuebersicht.class);

    List<Wahlvorschlag> wahlvorschlaege = wahlvorschlagDAO.findByWahl(wahlNotAttached).stream().filter(filter).filter(wahlvorschlag -> wahlvorschlag.getGebiet().isInGebietshierarchieVon(gebiet)) // aauch unterhalb der Wahlvorschlagsgebiete anzeigen
        .collect(Collectors.toList());

    ZulassungPruefer zulassungPruefer = zulassungPrueferDAOFactory.createZulassungPruefer();

    for (WahlvorschlagStatusFuerStatusuebersicht wahlvorschlagStatus : WahlvorschlagStatusFuerStatusuebersicht.values()) {
      result.put(wahlvorschlagStatus, wahlvorschlaege.stream().filter(entity -> wahlvorschlagStatus.hasWahlvorschlagStatus(entity, zulassungPruefer)).count());
    }

    return result;
  }

  public Map<WahlvorschlagStatusFuerStatusuebersicht, Long> getAnzahlListenkandidaturenProStatus(Wahl wahlNotAttached, Gebiet gebietNotAttached) {

    if (wahlNotAttached == null || gebietNotAttached == null) {
      return Collections.emptyMap();
    }

    Gebiet gebiet = gebietDAO.attach(gebietNotAttached);
    Map<WahlvorschlagStatusFuerStatusuebersicht, Long> result = new EnumMap<>(WahlvorschlagStatusFuerStatusuebersicht.class);

    List<Listenkandidatur> listenkandidaturen = listenkandidaturDAO.findByWahl(wahlNotAttached).stream().filter(listenkandidatur -> listenkandidatur.getGebiet().isInGebietshierarchieVon(gebiet)) // auch unterhalb der Wahlvorschlagsgebiete anzeigen
        .collect(Collectors.toList());

    ZulassungPruefer zulassungPruefer = zulassungPrueferDAOFactory.createZulassungPruefer();

    for (WahlvorschlagStatusFuerStatusuebersicht wahlvorschlagStatus : WahlvorschlagStatusFuerStatusuebersicht.values()) {
      result.put(wahlvorschlagStatus, listenkandidaturen.stream().filter(entity -> wahlvorschlagStatus.hasListenkandidaturStatus(entity, zulassungPruefer)).count());
    }

    return result;
  }
}
