
package de.ivu.elect.dokumente.kandidatur.statistik;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;

public class KandidaturenGebietsbezogenCache {

  private final Map<Gebiet, Set<Kandidatur>> kandidaturenGebietsbezogen = new HashMap<>();
  private final Collection<Kandidatur> alleKandidaturen;
  private final Function<Gebiet, Predicate<Kandidatur>> filterNachGebietFunction;

  public KandidaturenGebietsbezogenCache(Collection<Kandidatur> alleKandidaturen, Predicate<Kandidatur> kandidaturPredicate, Function<Gebiet, Predicate<Kandidatur>> filterNachGebietFunction) {
    this(alleKandidaturen.stream().filter(kandidaturPredicate).collect(Collectors.toList()), filterNachGebietFunction);
  }

  public KandidaturenGebietsbezogenCache(Collection<Kandidatur> alleKandidaturen, Function<Gebiet, Predicate<Kandidatur>> filterNachGebietFunction) {
    super();

    this.alleKandidaturen = alleKandidaturen;
    this.filterNachGebietFunction = filterNachGebietFunction;
  }

  public long getAnzahlKandidaturenInGebiet(Gebiet gebiet, GeschlechtFilter geschlecht, Predicate<Gruppe> parteienFilter) {
    return getKandidaturenInGebiet(gebiet).stream().filter(geschlecht.filterKandidaturen()).filter(lk -> parteienFilter.test(lk.getGruppe())).count();
  }

  private Set<Kandidatur> getKandidaturenInGebiet(Gebiet gebiet) {
    return kandidaturenGebietsbezogen.computeIfAbsent(gebiet, g -> computeKandidaturenInGebiet(gebiet));
  }

  private Set<Kandidatur> computeKandidaturenInGebiet(Gebiet gebiet) {
    Predicate<Kandidatur> kandidaturPredicate = filterNachGebietFunction.apply(gebiet);

    return alleKandidaturen.stream().filter(kandidaturPredicate).collect(Collectors.toSet());
  }
}
