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

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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

import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.niederschrift.entity.Niederschrift;
import de.ivu.elect.business.niederschrift.entity.NiederschriftArt;
import de.ivu.elect.business.niederschrift.entity.NiederschriftStatus;
import de.ivu.elect.business.niederschrift.entity.NiederschriftStatusAenderung;

@Stateless
public class NiederschriftStatusuebersicht {

  @Inject
  private transient NiederschriftDAO niederschriftDAO;

  @Inject
  private transient NiederschriftStatusAenderungDAO niederschriftStatusAenderungDAO;

  public Map<NiederschriftArt, Map<NiederschriftStatus, Map<String, Long>>> getAnzahlPerNiederschriftStatus(
      Collection<NiederschriftArt> niederschriftArten, Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {

    Map<NiederschriftArt, Map<NiederschriftStatus, Map<String, Long>>> result = initResultMap(niederschriftArten);

    List<Niederschrift> niederschriftenImGebiet = niederschriftDAO.findByWahl(wahldurchfuehrungsgebiet.getWahl())
        .stream() //
        .filter(niederschrift -> niederschriftArten.contains(niederschrift.getNiederschriftArt()) && niederschrift
            .getWahldurchfuehrungsgebiet().isInGebietshierarchieUntergeordnetesGebietVon(wahldurchfuehrungsgebiet))
        .collect(Collectors.toList());

    Map<Niederschrift, NiederschriftStatusAenderung> letzteStatusAenderungProNiederschrift = niederschriftStatusAenderungDAO
        .findByWahlAndMaxZeitstempel(wahldurchfuehrungsgebiet.getWahl()).stream()
        .collect(Collectors.toMap(NiederschriftStatusAenderung::getNiederschrift,
            niederschriftStatusAenderung -> niederschriftStatusAenderung));

    for (Niederschrift niederschrift : niederschriftenImGebiet) {
      NiederschriftStatusAenderung letzteStatusAenderung = letzteStatusAenderungProNiederschrift.get(niederschrift);
      if (letzteStatusAenderung == null) {
        increment(result, niederschrift.getNiederschriftArt(), null, null); // zählt zu unbekannt
      } else {
        increment(result, niederschrift.getNiederschriftArt(), letzteStatusAenderung.getStatus(),
            letzteStatusAenderung.getRaum());
      }
    }

    return result;
  }

  private Map<NiederschriftArt, Map<NiederschriftStatus, Map<String, Long>>> initResultMap(
      Collection<NiederschriftArt> niederschriftArten) {

    Map<NiederschriftArt, Map<NiederschriftStatus, Map<String, Long>>> result = new HashMap<>(
        niederschriftArten.size());

    for (NiederschriftArt niederschriftArt : niederschriftArten) {
      result.put(niederschriftArt, new HashMap<>());
    }

    return result;
  }

  private void increment(Map<NiederschriftArt, Map<NiederschriftStatus, Map<String, Long>>> result,
      NiederschriftArt art, NiederschriftStatus status, String raum) {

    Map<NiederschriftStatus, Map<String, Long>> anzahlProNiederschriftStatus = result.get(art);

    anzahlProNiederschriftStatus.putIfAbsent(status, new HashMap<>());

    anzahlProNiederschriftStatus.compute(status, (niederschriftStatus, anzahlProRaum) -> {
      anzahlProRaum.putIfAbsent(raum, 0L);
      anzahlProRaum.compute(raum, (s, anzahl) -> anzahl + 1);
      return anzahlProRaum;
    });
  }
}
