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

import de.ivu.elect.business.benutzerverwaltung.entity.Benutzer;
import de.ivu.elect.business.mandant.entity.EntityPKMitMandant;
import de.ivu.elect.business.system.boundary.SystemLogWriter;
import de.ivu.elect.business.system.entity.SystemLogQuelle;
import de.ivu.elect.business.wahl.entity.WahlOderWahlterminPK;
import de.ivu.elect.business.wahl.entity.WahlPK;
import de.ivu.elect.business.wahl.entity.WahlterminPK;
import de.ivu.elect.jee.faces.Messages;
import org.slf4j.Logger;

import javax.ejb.Asynchronous;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.inject.Inject;
import java.util.function.Consumer;

import static de.ivu.elect.business.mandant.entity.EntityPKMitMandant.from;

/**
 *  on 04.01.2017. abgeleitete Klasse mit @Stateless annotieren
 */
public abstract class AbstractElectMultipleCronTimerAsync<Payload> {

  protected static final Benutzer SYSTEM = Benutzer.SYSTEM;

  protected static final String SYSTEM_BENUTZERKENNUNG = SYSTEM.getBenutzerkennung();

  @Inject
  private transient Messages messages;

  @Inject
  private transient SystemLogWriter systemLogWriter;


  public AbstractElectMultipleCronTimerAsync() {
    super();
  }

  @Asynchronous
  @TransactionAttribute(TransactionAttributeType.NEVER)
  public void async(Object payload, Consumer finish) {
    try {
      handle((Payload) payload);
    } catch (Exception e) {
      systemLogWriter.writeErrorLogMessageFuerMandant(bestimmeMandant(payload), messages.getMessageForMessageKey("aysnc.timer.error", e.getMessage(), payload), e, getSystemLogQuelle());
    } finally {
      finish.accept(payload);
    }
  }

  public abstract SystemLogQuelle getSystemLogQuelle();

  protected abstract void handle(Payload payload) throws Exception;

  protected EntityPKMitMandant bestimmeMandant(Object payload) {
    if (payload != null) {
      try {
        return bestimmeMandantAusPayload((Payload) payload);
      } catch (Exception e) {
        getLog().warn("Mandant kann nicht aus Payload bestimmt werden: " + payload);
      }
    }
    return null;
  }

  protected abstract EntityPKMitMandant bestimmeMandantAusPayload(Payload payload);

  protected EntityPKMitMandant bestimmeMandant(WahlterminPK wahlterminPK) {
    return from(wahlterminPK);
  }

  protected EntityPKMitMandant bestimmeMandant(WahlOderWahlterminPK wahlOderWahlterminPK) {
    return from(wahlOderWahlterminPK);
  }

  protected EntityPKMitMandant bestimmeMandant(WahlPK wahlPK) {
    return from(wahlPK);
  }
  protected abstract Logger getLog();

}
