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

import de.ivu.elect.business.ergebnis.entity.ErgebnisPK;
import de.ivu.elect.business.mandant.entity.MandantPK;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import javax.ejb.Stateless;
import javax.inject.Inject;
import java.util.Date;

/**
 * Wegen ELECT-9427 nur mit PKs arbeiten
 * Zwischen der Übernahme und der Ergebnisberechnung wird der Hibernate-Cache gelöscht
 */
@Stateless
public class Zwischenergebnisberechnung {

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

  @Inject
  private transient ZwischenergebnisberechnungHelper zwischenergebnisberechnungHelper;

  private static ZwischenergebnisberechnungStatus zwischenergebnisberechnungStatus;

  public Zwischenergebnisberechnung() {
    super();
  }

  public boolean isErgebnisZuBerechnen(MandantPK mandantPK) {
    return zwischenergebnisberechnungHelper.isErgebnisZuBerechnen(mandantPK);
  }

  @Nullable
  public ErgebnisPK berechne(MandantPK mandantPK) {
    ErgebnisPK zuBerechnendesErgebnis = zwischenergebnisberechnungHelper.getZuBerechnendesErgebnis(mandantPK);
    if (zuBerechnendesErgebnis != null) {
      berechneErgebnis(zuBerechnendesErgebnis);
    }
    return zuBerechnendesErgebnis;
  }

  private void berechneErgebnis(ErgebnisPK ergebnisPK) {
    Date date = new Date();
    long start = date.getTime();
    try {
      boolean loeseKonflikte = false;
      createZwischenergebnisberechnungStatus(zwischenergebnisberechnungHelper.createZwischenergebnisberechnungStatus(ergebnisPK, loeseKonflikte, date));

      LOG.info("ErgebnisUebernehmen Ergebnis: " + ergebnisPK);
      zwischenergebnisberechnungHelper.ergebnisUebernehmen(ergebnisPK);

      LOG.info("ErgebnisUebernehmen Cache flushClear: " + ergebnisPK);
      zwischenergebnisberechnungHelper.flushClear();

      LOG.info("ErgebnisBerechnen Ergebnis: " + ergebnisPK);
      zwischenergebnisberechnungHelper.berechneErgebnis(ergebnisPK, loeseKonflikte, date);

    } finally {
      resetZwischenergebnisberechnungStatus();
      long dauerInMs = System.currentTimeMillis() - start;
      LOG.info("Berechne Ergebnis -  fertig, Dauer: " + dauerInMs + " ms, " + ergebnisPK);
    }
  }

  public static ZwischenergebnisberechnungStatus getZwischenergebnisberechnungStatus() {
    synchronized (Zwischenergebnisberechnung.class) {
      return zwischenergebnisberechnungStatus;
    }
  }

  private static void createZwischenergebnisberechnungStatus(ZwischenergebnisberechnungStatus zwischenergebnisberechnungStatus) {
    synchronized (Zwischenergebnisberechnung.class) {
      Zwischenergebnisberechnung.zwischenergebnisberechnungStatus = zwischenergebnisberechnungStatus;
    }
  }

  private static void resetZwischenergebnisberechnungStatus() {
    synchronized (Zwischenergebnisberechnung.class) {
      Zwischenergebnisberechnung.zwischenergebnisberechnungStatus = null;
    }
  }
}
