// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.config;

import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.git.WorkQueue.Task;
import com.google.inject.Inject;

import org.eclipse.jgit.internal.storage.file.WindowCacheStatAccessor;
import org.kohsuke.args4j.Option;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RequiresCapability(GlobalCapability.MAINTAIN_SERVER)
public class GetSummary implements RestReadView<ConfigResource> {

  private final WorkQueue workQueue;
  private final Path sitePath;

  @Option(name = "--gc", usage = "perform Java GC before retrieving memory stats")
  private boolean gc;

  public GetSummary setGc(boolean gc) {
    this.gc = gc;
    return this;
  }

  @Option(name = "--jvm", usage = "include details about the JVM")
  private boolean jvm;

  public GetSummary setJvm(boolean jvm) {
    this.jvm = jvm;
    return this;
  }

  @Inject
  public GetSummary(WorkQueue workQueue, @SitePath Path sitePath) {
    this.workQueue = workQueue;
    this.sitePath = sitePath;
  }

  @Override
  public SummaryInfo apply(ConfigResource rsrc)  {
    if (gc) {
      System.gc();
      System.runFinalization();
      System.gc();
    }

    SummaryInfo summary = new SummaryInfo();
    summary.taskSummary = getTaskSummary();
    summary.memSummary = getMemSummary();
    summary.threadSummary = getThreadSummary();
    if (jvm) {
      summary.jvmSummary = getJvmSummary();
    }
    return summary;
  }

  private TaskSummaryInfo getTaskSummary() {
    Collection<Task<?>> pending = workQueue.getTasks();
    int tasksTotal = pending.size();
    int tasksRunning = 0;
    int tasksReady = 0;
    int tasksSleeping = 0;
    for (Task<?> task : pending) {
      switch (task.getState()) {
        case RUNNING: tasksRunning++;
          break;
        case READY: tasksReady++;
          break;
        case SLEEPING: tasksSleeping++;
          break;
        case CANCELLED:
        case DONE:
        case OTHER:
          break;
      }
    }

    TaskSummaryInfo taskSummary = new TaskSummaryInfo();
    taskSummary.total = toInteger(tasksTotal);
    taskSummary.running = toInteger(tasksRunning);
    taskSummary.ready = toInteger(tasksReady);
    taskSummary.sleeping = toInteger(tasksSleeping);
    return taskSummary;
  }

  private MemSummaryInfo getMemSummary() {
    Runtime r = Runtime.getRuntime();
    long mMax = r.maxMemory();
    long mFree = r.freeMemory();
    long mTotal = r.totalMemory();
    long mInuse = mTotal - mFree;

    int jgitOpen = WindowCacheStatAccessor.getOpenFiles();
    long jgitBytes = WindowCacheStatAccessor.getOpenBytes();

    MemSummaryInfo memSummaryInfo = new MemSummaryInfo();
    memSummaryInfo.total = bytes(mTotal);
    memSummaryInfo.used = bytes(mInuse - jgitBytes);
    memSummaryInfo.free = bytes(mFree);
    memSummaryInfo.buffers = bytes(jgitBytes);
    memSummaryInfo.max = bytes(mMax);
    memSummaryInfo.openFiles = toInteger(jgitOpen);
    return memSummaryInfo;
  }

  private ThreadSummaryInfo getThreadSummary() {
    Runtime r = Runtime.getRuntime();
    ThreadSummaryInfo threadInfo = new ThreadSummaryInfo();
    threadInfo.cpus = r.availableProcessors();
    threadInfo.threads = toInteger(ManagementFactory.getThreadMXBean().getThreadCount());

    List<String> prefixes = Arrays.asList("HTTP", "IntraLineDiff", "ReceiveCommits",
        "SSH git-receive-pack", "SSH git-upload-pack", "SSH-Interactive-Worker",
        "SSH-Stream-Worker", "SshCommandStart");
    String other = "Other";
    ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

    threadInfo.counts = new HashMap<>();
    for (long id : threadMXBean.getAllThreadIds()) {
      ThreadInfo info = threadMXBean.getThreadInfo(id);
      if (info == null) {
        continue;
      }
      String name = info.getThreadName();
      Thread.State state = info.getThreadState();
      String group = other;
      for (String p : prefixes) {
        if (name.startsWith(p)) {
          group = p;
          break;
        }
      }
      Map<Thread.State, Integer> counts = threadInfo.counts.get(group);
      if (counts == null) {
        counts = new HashMap<>();
        threadInfo.counts.put(group, counts);
      }
      Integer c = counts.get(state);
      counts.put(state, c != null ? c + 1 : 1);
    }

    return threadInfo;
  }

  private JvmSummaryInfo getJvmSummary() {
    OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
    RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();

    JvmSummaryInfo jvmSummary = new JvmSummaryInfo();
    jvmSummary.vmVendor = runtimeBean.getVmVendor();
    jvmSummary.vmName = runtimeBean.getVmName();
    jvmSummary.vmVersion = runtimeBean.getVmVersion();
    jvmSummary.osName = osBean.getName();
    jvmSummary.osVersion = osBean.getVersion();
    jvmSummary.osArch = osBean.getArch();
    jvmSummary.user = System.getProperty("user.name");

    try {
      jvmSummary.host = InetAddress.getLocalHost().getHostName();
    } catch (UnknownHostException e) {
      // Ignored
    }

    jvmSummary.currentWorkingDirectory =
        path(Paths.get(".").toAbsolutePath().getParent());
    jvmSummary.site = path(sitePath);
    return jvmSummary;
  }

  private static Integer toInteger(int i) {
    return i != 0 ? i : null;
  }

  private static String bytes(double value) {
    value /= 1024;
    String suffix = "k";

    if (value > 1024) {
      value /= 1024;
      suffix = "m";
    }
    if (value > 1024) {
      value /= 1024;
      suffix = "g";
    }
    return String.format("%1$6.2f%2$s", value, suffix).trim();
  }

  private static String path(Path path) {
    try {
      return path.toRealPath().normalize().toString();
    } catch (IOException err) {
      return path.toAbsolutePath().normalize().toString();
    }
  }

  public static class SummaryInfo {
    public TaskSummaryInfo taskSummary;
    public MemSummaryInfo memSummary;
    public ThreadSummaryInfo threadSummary;
    public JvmSummaryInfo jvmSummary;
  }

  public static class TaskSummaryInfo {
    public Integer total;
    public Integer running;
    public Integer ready;
    public Integer sleeping;
  }

  public static class MemSummaryInfo {
    public String total;
    public String used;
    public String free;
    public String buffers;
    public String max;
    public Integer openFiles;
  }

  public static class ThreadSummaryInfo {
    public Integer cpus;
    public Integer threads;
    public Map<String, Map<Thread.State, Integer>> counts;
  }

  public static class JvmSummaryInfo {
    public String vmVendor;
    public String vmName;
    public String vmVersion;
    public String osName;
    public String osVersion;
    public String osArch;
    public String user;
    public String host;
    public String currentWorkingDirectory;
    public String site;
  }
}
