package de.ivu.elect.jee.performance;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

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


import static de.ivu.elect.jee.session.SessionIdFilter.maskiere;

public class PerformanceStore {

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

  private static final AtomicBoolean ENABLED = new AtomicBoolean(false);

  private static final AtomicBoolean LOGGING_ENABLED = new AtomicBoolean(false);

  private static final Map<ViewAccessTarget, ViewAccessDynamic> VIEW_MAP = new ConcurrentHashMap<>();

  public static void destroySession(String id) {
    if (StringUtils.isBlank(id)) {
      return;
    }
    LOG.debug("destroy session: " + maskiere(id) + " verschiebe Statistiken");

    ArrayList<Map.Entry<ViewAccessTarget, ViewAccessDynamic>> entries = new ArrayList<>(VIEW_MAP.entrySet());

    for (Map.Entry<ViewAccessTarget, ViewAccessDynamic> entry : entries) {
      ViewAccessTarget key = entry.getKey();
      if (id.equals(key.getSessionId())) {
        ViewAccessDynamic value = entry.getValue();
        addCounterAndDuration(ViewAccessTarget.copyNewSessionId(key, ViewAccessTarget.SESSION_ID_OHNE), value.getCounter(), value.getTimeTotal());
        VIEW_MAP.remove(key);
      }
    }

    LOG.debug("destroy session: " + maskiere(id) + " verschiebe Statistiken - done");
  }

  public static void addDuration(ViewAccessTarget viewAccessTarget, long duration) {
    VIEW_MAP.computeIfAbsent(viewAccessTarget, i -> new ViewAccessDynamic()).addDuration(duration);
    if (isStatistikLoggingAktiviert()) {
      LOG.info("Statistik geloggt: " + viewAccessTarget + "; Dauer: " + duration);
    }
  }

  private static void addCounterAndDuration(ViewAccessTarget viewAccessTarget, long counter, long duration) {
    VIEW_MAP.computeIfAbsent(viewAccessTarget, i -> new ViewAccessDynamic()).addCounterAndDuration(counter, duration);
  }

  public static void resetStatistik() {
    VIEW_MAP.clear();
  }

  public static ViewAccessStatistics getStatictics() {
    List<ViewAccessTargetStatistics> statistics = new ArrayList<>(VIEW_MAP.size() + 1);
    long timestamp = System.currentTimeMillis();
    VIEW_MAP.forEach((key, value) -> statistics.add(new ViewAccessTargetStatistics(key, value.getCounter(), value.getTimeTotal())));
    return new ViewAccessStatistics(timestamp, statistics);
  }

  public static String logStatistics() {
    if (isStatistikAktiviert()) {
      String result = getStatictics().toJson();
      LOG.info("Performance-Statistik:" + result);
      return result;
    }
    return "";
  }

  public static boolean isStatistikAktiviert() {
    return ENABLED.get();
  }

  public static void deaktiviereStatistik() {
    ENABLED.set(false);
  }

  public static void aktiviereStatistik() {
    ENABLED.set(true);
  }
  public static boolean isStatistikLoggingAktiviert() {
    return LOGGING_ENABLED.get();
  }

  public static void deaktiviereStatistikLogging() {
    LOGGING_ENABLED.set(false);
  }

  public static void aktiviereStatistikLogging() {
    LOGGING_ENABLED.set(true);
  }

}
