
package de.ivu.elect.business.stimmeingabe.control.sequenznummer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.ergebnis.entity.ZwischenergebnisBerechnenEvent;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.stimmeingabe.boundary.ErgebniseingangDAO;
import de.ivu.elect.business.stimmeingabe.control.ErgebniseingangEingangssequenznummerGenerator;
import de.ivu.elect.business.stimmeingabe.control.LetzterEingangCache;
import de.ivu.elect.business.stimmeingabe.entity.AbstractErgebniseingang;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;

@Stateless
public class ErgebnissequenznummerSetzen {

  private static final Logger LOG = LoggerFactory.getLogger(ErgebnissequenznummerSetzen.class);

  @Inject
  private transient ErgebniseingangDAO ergebniseingangDAO;

  @Inject
  private transient ErgebniseingangEingangssequenznummerGenerator ergebniseingangEingangssequenznummerGenerator;

  @Inject
  private transient ZwischenergebnisBerechnenEvent zwischenergebnisBerechnenEvent;

  @Inject
  private transient LetzterEingangCache letzterEingangCache;

  @Inject
  private transient ErgebnissequenznummerFuerGebietGesetztEvent ergebnissequenznummerFuerGebietGesetztEvent;

  public ErgebnissequenznummerSetzen() {
    super();
  }

  public boolean isErgebnissequenznummerSetzenNotwendig() {
    return ergebniseingangDAO.findByCountErgebnissequenznummerIsNull() > 0L;
  }

  public void setzeErgebnissequenznummern() {
    List<Ergebniseingang> ergebniseingaengeOhneErgebnissequenznummer = ergebniseingangDAO.findByErgebnissequenznummerIsNull();

    LOG.info("Setze Ergebnissequenznummern an ins Ergebnis uebernehmbaren Ergebniseingaengen - START [ergebniseingaenge ohne ergebnissequenznummer = "
        + ergebniseingaengeOhneErgebnissequenznummer.size() + "]");

    Map<Wahldurchfuehrungsgebiet, List<Ergebniseingang>> ergebniseingangInErgebnisUebernehmbarPerWahldurchfuehrungsgebiet = new HashMap<>();

    for (Ergebniseingang ergebniseingang : ergebniseingaengeOhneErgebnissequenznummer) {
      Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = ergebniseingang.getWahldurchfuehrungsgebiet();

      letzterEingangCache.setzeLetztenEingangWennNeuer(ergebniseingang); //
      // wahldurchfuehrungsgebiet.setzeLetztenEingangWennNeuer(ergebniseingang); // ELECTMUC-2852

      if (ergebniseingang.isInErgebnisUebernehmbar()) {
        ergebniseingangInErgebnisUebernehmbarPerWahldurchfuehrungsgebiet.computeIfAbsent(wahldurchfuehrungsgebiet, x -> new ArrayList<>()).add(ergebniseingang);
      } else {
        ergebniseingang.setErgebnissequenznummer(AbstractErgebniseingang.ERGEBNISSEQUENZNUMMER_UNGUELTIG);
      }
    }

    for (Map.Entry<Wahldurchfuehrungsgebiet, List<Ergebniseingang>> entry : ergebniseingangInErgebnisUebernehmbarPerWahldurchfuehrungsgebiet.entrySet()) {
      Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = entry.getKey();
      List<Ergebniseingang> ergebniseingaenge = entry.getValue();

      for (Ergebniseingang ergebniseingang : ergebniseingaenge) {
        ergebniseingang.setErgebnissequenznummer(ergebniseingangEingangssequenznummerGenerator.getNaechsteEingangssequenznummer());
      }

      ergebnissequenznummerFuerGebietGesetztEvent.sendEvent(wahldurchfuehrungsgebiet);
    }

    LOG.info("Setze Ergebnissequenznummern an ins Ergebnis uebernehmbaren Ergebniseingaengen - DONE [ergebniseingaenge ergebnissequenznummer gesetzt = "
        + ergebniseingaengeOhneErgebnissequenznummer.size() + ", davon ergebniseingaenge ins Ergebnis uebernehmbar = " + ergebniseingangInErgebnisUebernehmbarPerWahldurchfuehrungsgebiet.size() + "]");

    zwischenergebnisBerechnenEvent.sendChangeEvent();
  }
}
