
package de.ivu.elect.business.statistik.control;

import java.util.Date;
import java.util.List;

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

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

import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.statistik.boundary.StatistikKennzeichenDAO;
import de.ivu.elect.business.statistik.boundary.StatistikLaufDAO;
import de.ivu.elect.business.statistik.entity.StatistikKennzeichen;
import de.ivu.elect.business.statistik.entity.StatistikLauf;
import de.ivu.elect.business.statistik.entity.StatistikLaufStatus;
import de.ivu.elect.business.system.boundary.SystemLogWriter;
import de.ivu.elect.business.system.entity.SystemLogQuelle;
import de.ivu.elect.business.wahl.boundary.WahlDAO;

@Stateless
public class StatistikLaufBerechner {

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

  private static final int ANZAHL_PRO_TRANSAKTION = 1;

  @Inject
  private transient WahlDAO wahlDAO;

  @Inject
  private transient GebietDAO gebietDAO;

  @Inject
  private transient StatistikKennzeichenDAO statistikKennzeichenDAO;

  @Inject
  private transient StatistikLaufDAO statistikLaufDAO;

  @Inject
  private transient StatistikLaufBerechnerGebieteSupplier statistikLaufBerechnerGebieteSupplier;

  @Inject
  private transient StatistikLaufBerechnerFuerGebiet statistikLaufBerechnerFuerGebiet;

  @Inject
  private transient SystemLogWriter systemLogWriter;

  public StatistikLaufBerechner() {
    super();
  }

  public boolean isSomethingToDo() {
    return !getStatistikLaeufeByStatus().isEmpty();
  }

  protected List<StatistikLauf> getStatistikLaeufeByStatus() {
    return statistikLaufDAO.findByStatus(StatistikLaufStatus.ZU_BERECHNEN, ANZAHL_PRO_TRANSAKTION);
  }

  public void berechne() {
    for (StatistikLauf statistikLauf : getStatistikLaeufeByStatus()) {
      try {
        LOG.info("Berechne Lauf: " + statistikLauf);
        statistikLauf.setStartDesLaufs(new Date());
        statistikKennzeichenDAO.deleteByLauf(statistikLauf); // Erstmal alles Löschen, vielleicht abgestürzt und Berechnung war unvollständig...

        for (Gebiet gebiet : statistikLaufBerechnerGebieteSupplier.getGebieteFuerStatistikBerechnung(statistikLauf)) {
          LOG.info("Berechne Gebiet = " + gebiet);
          List<StatistikKennzeichen> kennzeichen = statistikLaufBerechnerFuerGebiet.berechneStatistikKennzeichenFuerGebiet(statistikLauf, gebiet);

          for (StatistikKennzeichen statistikKennzeichen : kennzeichen) {
            statistikKennzeichen.setWahl(wahlDAO.attach(statistikKennzeichen.getWahl()));
            statistikKennzeichen.setGebiet(gebietDAO.attach(statistikKennzeichen.getGebiet()));
            statistikKennzeichen.setStatistikLauf(statistikLauf);

            statistikKennzeichenDAO.persist(statistikKennzeichen);
          }
        }

        LOG.info("Berechne Lauf: " + statistikLauf + " - done");
        statistikLauf.setEndeDesLaufs(new Date());
        statistikLauf.setStatus(StatistikLaufStatus.BERECHNET);
      } catch (Exception ex) {
        systemLogWriter.writeErrorLogMessageFuerMandant(statistikLauf, "Statistiklauf nicht berechnet " + statistikLauf, ex, SystemLogQuelle.STATISTIK_LAUF);

        statistikLaufBerechnerFuerGebiet.markiereFehlerhaft(statistikLauf, ex.getLocalizedMessage());

        // ELECT-12326, Änderungen aus vorheriger Transaktion "sichtbar" machen...
        statistikLaufDAO.refresh(statistikLauf);

        return; // Nächster Statistiklauf...
      }
    }
  }
}
