/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.test.dunit.internal;

import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_NETWORK_PARTITION_DETECTION;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.SystemUtils;

import org.apache.geode.distributed.ConfigurationProperties;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.InternalLocator;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.version.VersionManager;

class ProcessManager implements ChildVMLauncher {
  private int namingPort;
  private Map<Integer, ProcessHolder> processes = new HashMap<>();
  private File log4jConfig;
  private int pendingVMs;
  private Registry registry;
  private int debugPort = Integer.getInteger("dunit.debug.basePort", 0);
  private int suspendVM = Integer.getInteger("dunit.debug.suspendVM", -100);
  private VersionManager versionManager;

  public ProcessManager(int namingPort, Registry registry) {
    this.versionManager = VersionManager.getInstance();
    this.namingPort = namingPort;
    this.registry = registry;
  }

  public synchronized void launchVM(int vmNum) throws IOException {
    launchVM(VersionManager.CURRENT_VERSION, vmNum, false);
  }

  @Override
  public synchronized ProcessHolder launchVM(String version, int vmNum, boolean bouncedVM)
      throws IOException {
    if (bouncedVM) {
      processes.remove(vmNum);
    }
    if (processes.containsKey(vmNum)) {
      throw new IllegalStateException("VM " + vmNum + " is already running.");
    }

    File workingDir = getVMDir(version, vmNum);
    if (!workingDir.exists()) {
      workingDir.mkdirs();
    } else if (!bouncedVM || DUnitLauncher.MAKE_NEW_WORKING_DIRS) {
      try {
        FileUtils.deleteDirectory(workingDir);
      } catch (IOException e) {
        // This delete is occasionally failing on some platforms, maybe due to a lingering
        // process. Allow the process to be launched anyway.
        System.err.println("Unable to delete " + workingDir + ". Currently contains "
            + Arrays.asList(workingDir.list()));
      }
      workingDir.mkdirs();
    }

    String[] cmd = buildJavaCommand(vmNum, namingPort, version);
    System.out.println("Executing " + Arrays.toString(cmd));

    if (log4jConfig != null) {
      FileUtils.copyFileToDirectory(log4jConfig, workingDir);
    }

    // TODO - delete directory contents, preferably with commons io FileUtils
    try {
      Process process = Runtime.getRuntime().exec(cmd, null, workingDir);
      pendingVMs++;
      ProcessHolder holder = new ProcessHolder(process);
      processes.put(vmNum, holder);
      linkStreams(version, vmNum, holder, holder.getErrorStream(), System.err);
      linkStreams(version, vmNum, holder, holder.getInputStream(), System.out);
      return holder;
    } catch (RuntimeException | Error t) {
      t.printStackTrace();
      throw t;
    }
  }

  public void validateVersion(String version) {
    if (!versionManager.isValidVersion(version)) {
      throw new IllegalArgumentException("Version " + version + " is not configured for use");
    }
  }

  public static File getVMDir(String version, int vmNum) {
    return new File(DUnitLauncher.DUNIT_DIR, VM.getVMName(VersionManager.CURRENT_VERSION, vmNum));
  }

  public synchronized void killVMs() {
    for (ProcessHolder process : processes.values()) {
      if (process != null) {
        process.kill();
      }
    }
  }

  public synchronized boolean hasLiveVMs() {
    for (ProcessHolder process : processes.values()) {
      if (process != null && process.isAlive()) {
        return true;
      }
    }
    return false;
  }

  @Deprecated
  public synchronized void bounce(String version, int vmNum, boolean force) {
    if (!processes.containsKey(vmNum)) {
      throw new IllegalStateException("No such process " + vmNum);
    }
    try {
      ProcessHolder holder = processes.remove(vmNum);
      if (force) {
        holder.killForcibly();
      } else {
        holder.kill();
      }
      holder.waitFor();
      System.out.println("Old process for vm_" + vmNum + " has exited");
      launchVM(version, vmNum, true);
    } catch (InterruptedException | IOException e) {
      throw new RuntimeException("Unable to restart VM " + vmNum, e);
    }
  }

  private void linkStreams(final String version, final int vmNum, final ProcessHolder holder,
      final InputStream in, final PrintStream out) {
    final String vmName = "[" + VM.getVMName(version, vmNum) + "] ";
    Thread ioTransport = new Thread() {
      @Override
      public void run() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        try {
          String line = reader.readLine();
          while (line != null) {
            if (line.length() == 0) {
              out.println();
            } else {
              out.print(vmName);
              out.println(line);
            }
            line = reader.readLine();
          }
        } catch (Exception e) {
          if (!holder.isKilled()) {
            out.println("Error transporting IO from child process");
            e.printStackTrace(out);
          }
        }
      }
    };

    ioTransport.setDaemon(true);
    ioTransport.start();
  }

  private String removeModulesFromPath(String classpath, String... modules) {
    for (String module : modules) {
      classpath = removeModuleFromGradlePath(classpath, module);
      classpath = removeModuleFromEclipsePath(classpath, module);
    }
    return classpath;
  }

  private String removeModuleFromEclipsePath(String classpath, String module) {
    String buildDir = File.separator + module + File.separator + "out" + File.separator;

    String mainClasses = buildDir + "production";

    classpath = removeFromPath(classpath, mainClasses);
    return classpath;
  }

  private String removeModuleFromGradlePath(String classpath, String module) {
    String buildDir = File.separator + module + File.separator + "build" + File.separator;

    String mainClasses = buildDir + "classes" + File.separator + "java" + File.separator + "main";
    classpath = removeFromPath(classpath, mainClasses);

    String libDir = buildDir + "libs";
    classpath = removeFromPath(classpath, libDir);

    String mainResources = buildDir + "resources" + File.separator + "main";
    classpath = removeFromPath(classpath, mainResources);

    String generatedResources = buildDir + "generated-resources" + File.separator + "main";
    classpath = removeFromPath(classpath, generatedResources);

    return classpath;
  }

  private String[] buildJavaCommand(int vmNum, int namingPort, String version) {
    String cmd = System.getProperty("java.home") + File.separator
        + "bin" + File.separator + "java";
    String dunitClasspath = System.getProperty("java.class.path");
    String separator = File.separator;
    String classPath;
    if (VersionManager.isCurrentVersion(version)) {
      classPath = dunitClasspath;
    } else {
      // remove current-version product classes and resources from the classpath
      dunitClasspath =
          removeModulesFromPath(dunitClasspath, "geode-core", "geode-cq", "geode-common",
              "geode-json", "geode-lucene",
              "geode-wan");
      classPath = versionManager.getClasspath(version) + File.pathSeparator + dunitClasspath;
    }

    // String tmpDir = System.getProperty("java.io.tmpdir");
    String agent = getAgentString();

    String jdkDebug = "";
    if (debugPort > 0) {
      jdkDebug += ",address=" + debugPort;
      debugPort++;
    }

    String jdkSuspend = vmNum == suspendVM ? "y" : "n"; // ignore version
    ArrayList<String> cmds = new ArrayList<String>();
    cmds.add(cmd);
    cmds.add("-classpath");
    String jreLib = separator + "jre" + separator + "lib" + separator;
    classPath = removeFromPath(classPath, jreLib);
    cmds.add(classPath);
    cmds.add("-D" + DUnitLauncher.RMI_PORT_PARAM + "=" + namingPort);
    cmds.add("-D" + DUnitLauncher.VM_NUM_PARAM + "=" + vmNum);
    cmds.add("-D" + DUnitLauncher.VM_VERSION_PARAM + "=" + version);
    cmds.add("-D" + DUnitLauncher.WORKSPACE_DIR_PARAM + "=" + new File(".").getAbsolutePath());
    if (vmNum >= 0) { // let the locator print a banner
      if (version.equals(VersionManager.CURRENT_VERSION)) { // enable the banner for older versions
        cmds.add("-D" + InternalLocator.INHIBIT_DM_BANNER + "=true");
      }
    } else {
      // most distributed unit tests were written under the assumption that network partition
      // detection is disabled, so we turn it off in the locator. Tests for network partition
      // detection should create a separate locator that has it enabled
      cmds.add(
          "-D" + DistributionConfig.GEMFIRE_PREFIX + ENABLE_NETWORK_PARTITION_DETECTION + "=false");
      cmds.add(
          "-D" + DistributionConfig.GEMFIRE_PREFIX + "allow_old_members_to_join_for_testing=true");
    }
    cmds.add("-D" + LOG_LEVEL + "=" + DUnitLauncher.logLevel);
    if (DUnitLauncher.LOG4J != null) {
      cmds.add("-Dlog4j.configurationFile=" + DUnitLauncher.LOG4J);
    }
    cmds.add("-Djava.library.path=" + System.getProperty("java.library.path"));
    cmds.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=" + jdkSuspend + jdkDebug);
    cmds.add("-XX:+HeapDumpOnOutOfMemoryError");
    cmds.add("-Xmx512m");
    cmds.add("-D" + DistributionConfig.GEMFIRE_PREFIX + "DEFAULT_MAX_OPLOG_SIZE=10");
    cmds.add("-D" + DistributionConfig.GEMFIRE_PREFIX + "disallowMcastDefaults=true");
    cmds.add("-D" + DistributionConfig.RESTRICT_MEMBERSHIP_PORT_RANGE + "=true");
    cmds.add("-D" + DistributionConfig.GEMFIRE_PREFIX
        + ConfigurationProperties.VALIDATE_SERIALIZABLE_OBJECTS + "=true");
    cmds.add("-ea");
    cmds.add("-XX:MetaspaceSize=512m");
    cmds.add("-XX:SoftRefLRUPolicyMSPerMB=1");
    cmds.add(agent);
    if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9)) {
      // needed for client stats gathering, see VMStats50 class, it's using class inspection
      // to call getProcessCpuTime method
      cmds.add("--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED");
      // needed for server side code
      cmds.add("--add-opens=java.xml/jdk.xml.internal=ALL-UNNAMED");
      cmds.add("--add-opens=java.base/jdk.internal.module=ALL-UNNAMED");
      cmds.add("--add-opens=java.base/java.lang.module=ALL-UNNAMED");
    }
    cmds.add(ChildVM.class.getName());
    String[] rst = new String[cmds.size()];
    cmds.toArray(rst);

    return rst;
  }

  private String removeFromPath(String classpath, String partialPath) {
    String[] jars = classpath.split(File.pathSeparator);
    StringBuilder sb = new StringBuilder(classpath.length());
    Boolean firstjar = true;
    for (String jar : jars) {
      if (!jar.contains(partialPath)) {
        if (!firstjar) {
          sb.append(File.pathSeparator);
        }
        sb.append(jar);
        firstjar = false;
      }
    }
    return sb.toString();
  }

  /**
   * Get the java agent passed to this process and pass it to the child VMs. This was added to
   * support jacoco code coverage reports
   */
  private String getAgentString() {
    RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
    if (runtimeBean != null) {
      for (String arg : runtimeBean.getInputArguments()) {
        if (arg.contains("-javaagent:")) {
          // HACK for gradle bug GRADLE-2859. Jacoco is passing a relative path
          // That won't work when we pass this to dunit VMs in a different
          // directory
          arg = arg.replace("-javaagent:..",
              "-javaagent:" + System.getProperty("user.dir") + File.separator + "..");
          arg = arg.replace("destfile=..",
              "destfile=" + System.getProperty("user.dir") + File.separator + "..");
          return arg;
        }
      }
    }

    return "-DdummyArg=true";
  }

  synchronized void signalVMReady() {
    pendingVMs--;
    this.notifyAll();
  }

  public synchronized boolean waitForVMs() throws InterruptedException {
    return waitForVMs(DUnitLauncher.STARTUP_TIMEOUT);
  }

  public synchronized boolean waitForVMs(long timeout) throws InterruptedException {
    long end = System.currentTimeMillis() + timeout;
    while (pendingVMs > 0) {
      long remaining = end - System.currentTimeMillis();
      if (remaining <= 0) {
        return false;
      }
      this.wait(remaining);
    }

    return true;
  }

  @Override
  public RemoteDUnitVMIF getStub(int i)
      throws RemoteException, NotBoundException, InterruptedException {
    return getStub(VersionManager.CURRENT_VERSION, i);
  }

  public RemoteDUnitVMIF getStub(String version, int i)
      throws RemoteException, NotBoundException, InterruptedException {
    waitForVMs(DUnitLauncher.STARTUP_TIMEOUT);
    return (RemoteDUnitVMIF) registry.lookup("vm" + i);
  }

  public ProcessHolder getProcessHolder(int i) {
    return processes.get(i);
  }
}
