package de.ivu.elect.jee.protokollierung;

import java.util.Date;
import java.util.function.Supplier;

import javax.faces.context.FacesContext;

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.jee.cdi.BeanManagerUtil;
import de.ivu.elect.jee.cdi.TransactionSynchronizationRegistryUtil;
import de.ivu.elect.jee.security.AbstractPrincipal;
import de.ivu.elect.jee.security.PrincipalMarker;

public class ProtokollThreadLocal {

  private static final ThreadLocal<Protokoll> event = new ThreadLocal<>();

  public static Protokoll remove() {
    Protokoll result = event.get();
    event.remove();
    return result;
  }

  public static Protokoll get() {
    return event.get();
  }

  /**
   * liefert das Protokoll, erzeugt ein neues und verschickt das ProtokollEvent, wenn noch kein Protokoll existiert
   */
  public static Protokoll getOrCreate() {
    return getOrCreate(ProtokollThreadLocal::getBenutzerKennung);
  }

  private static Protokoll getOrCreate(Supplier<String> benutzerkennung) {
    Protokoll result = event.get();
    if (result == null) {
      result = new Protokoll(benutzerkennung.get());
      event.set(result);
      TransactionSynchronizationRegistryUtil.getTransactionSynchronizationRegistry().registerInterposedSynchronization(new ProtokollSynchronization());
    }

    return result;
  }

  public static void setBenutzerKennung(String benutzerKennung) {
    getOrCreate(() -> benutzerKennung).setBenutzerkennung(benutzerKennung);
  }

  public static void setZeitpunkt(Date zeitpunkt) {
    getOrCreate().setZeitpunkt(zeitpunkt);
  }

  public static String getBenutzerKennung() {
    String result = null;
    if (isSessionActive()) {
      try {
        PrincipalMarker principal = BeanManagerUtil.getBeanByClass(PrincipalMarker.class);
        result = principal.getNameFuerProtokollierung();
      } catch (Exception e) {
        // ignorieren => wahrscheinlich Systeminteraktion ohne aktiven Context
        result = null;
      }
    }
    if (StringUtils.isBlank(result)) {
      result = AbstractPrincipal.SYSTEM_BENUTZERKENNUNG;
    }

    return result;
  }

  private static boolean isSessionActive() {
    try {
      return FacesContext.getCurrentInstance().getExternalContext().getSessionId(false) != null;
    } catch (Exception e) {
      return false;
    }

  }
}
