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

import java.util.Optional;

import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.benutzerverwaltung.entity.Benutzer;
import de.ivu.elect.business.konfiguration.entity.ElectLogLevel;
import de.ivu.elect.business.konfiguration.entity.KonfigurationLoader;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.control.ElectCommonPrincipal;
import de.ivu.elect.jee.performance.PerformanceLog;
import de.ivu.elect.jee.performance.PerformanceLogTransactionHandling;
import de.ivu.elect.jee.performance.ViewType;
import de.ivu.elect.jee.security.AbstractPrincipal;

@PerformanceLog(viewType = ViewType.INTERFACE, transactionHandling = PerformanceLogTransactionHandling.IMMEDIATELY)
public abstract class AbstractBaseWebService {

  protected static final String SYSTEM_USER_NAME_LEGACY_VALUE = StringUtils.capitalize(StringUtils.lowerCase(Benutzer.SYSTEM.getFamilienname()));

  @Inject
  private transient ElectCommonPrincipal principal;

  @Inject
  private transient KonfigurationLoader konfigurationLoader;

  private final Logger log;

  public AbstractBaseWebService() {
    super();

    this.log = LoggerFactory.getLogger(this.getClass());
  }

  protected KonfigurationLoader getKonfigurationLoader() {
    return konfigurationLoader;
  }

  protected String getActivePrincipalNameOrDefault() {
    return getPrincipal().map(AbstractPrincipal::getName).orElse(SYSTEM_USER_NAME_LEGACY_VALUE);
  }

  protected boolean isActivePrincipalHavingUseCasePermission(UseCasePermission useCasePermission) {
    return getPrincipal().map(principal -> principal.hasUseCasePermission(useCasePermission)).orElse(false);
  }

  private Optional<ElectCommonPrincipal> getPrincipal() {
    try {
      principal.getName();

      return Optional.of(principal);
    } catch (RuntimeException ignored) {
      // NOTE, dass der Zugriff auf ElectCommonPrincipal einen aktiven Context voraussetzt, der beim Aufruf des Service über einen Hintergrundprozess,
      // bspw. EWO-Abgleich im Hintergrund, nicht vorhanden ist, cf. ELECT-6790 "No active contexts for scope type javax.enterprise.context.SessionScoped"!
      debug(ignored.getMessage(), ignored);
    }

    return Optional.empty();
  }

  protected void debug(String format, Object... params) {
    log.debug(format, params);
  }

  protected void debug(String format, Throwable cause) {
    log.debug(format, cause);
  }

  protected void info(String format, Object... params) {
    log.info(format, params);
  }

  protected void warn(String format, Object... params) {
    log.warn(format, params);
  }

  protected void warn(String format, Throwable cause) {
    log.warn(format, cause);
  }

  protected void error(String format, Object... params) {
    log.error(format, params);
  }

  protected void error(String format, Throwable cause) {
    log.error(format, cause);
  }

  public ElectLogLevel getLogLevel(Mandant mandant) {
    return ElectLogLevel.DEAKTIVIERT;
  }

  protected void debugLog(Mandant mandant, String format, Object... params) {
    if (getLogLevel(mandant).isDebug()) {
      info(format, params);
    }
  }

  protected void errorLog(Mandant mandant, String format, Throwable t) {
    if (getLogLevel(mandant).isDebug()) {
      error(format, t);
    }
  }

  protected void traceLog(Mandant mandant, String format, Object... params) {
    if (getLogLevel(mandant).isTrace()) {
      info(format, params);
    }
  }
}
