/*
 * 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.process;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.regex.Pattern;

import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.SystemUtils;
import org.apache.logging.log4j.Logger;

import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.test.awaitility.GeodeAwaitility;

/**
 * Wraps spawned {@link Process} to capture output and provide interaction with the process.
 *
 * @since GemFire 4.1.1
 */
public class ProcessWrapper implements Consumer<String> {
  private static final Logger logger = LogService.getLogger();

  private static final long PROCESS_TIMEOUT_MILLIS = GeodeAwaitility.getTimeout().getValueInMS();
  private static final long DELAY = 10;

  private final boolean headless;
  private final long timeoutMillis;
  private final File directory;

  private final String[] jvmArguments;

  private final Class<?> mainClass;
  private final String[] mainArguments;

  private volatile Process process;
  private volatile Throwable processException;
  private volatile ProcessOutputReader outputReader;

  private final boolean useMainLauncher;

  private final List<String> allLines;
  private final BlockingQueue<String> lineBuffer;

  private final AtomicInteger exitValue = new AtomicInteger(-1);
  private boolean starting;
  private boolean started;
  private boolean stopped;
  private boolean interrupted;
  private Thread processThread;
  private ProcessStreamReader stdout;
  private ProcessStreamReader stderr;
  private Consumer<String> consumer;

  private ProcessWrapper(final String[] jvmArguments, final Class<?> mainClass,
      final String[] mainArguments, final boolean useMainLauncher, final boolean headless,
      final long timeoutMillis, final File directory) {
    this.jvmArguments = jvmArguments;
    this.mainClass = mainClass;
    this.mainArguments = mainArguments;
    this.useMainLauncher = useMainLauncher;
    this.headless = headless;
    this.timeoutMillis = timeoutMillis;
    this.directory = directory;

    lineBuffer = new LinkedBlockingQueue<>();
    allLines = Collections.synchronizedList(new ArrayList<>());
  }

  public void setConsumer(Consumer<String> consumer) {
    this.consumer = consumer;
  }

  @Override
  public void accept(String line) {
    allLines.add(line);
    lineBuffer.offer(line);

    if (consumer != null) {
      consumer.accept(line);
    }
  }

  public ProcessStreamReader getStandardOutReader() {
    synchronized (exitValue) {
      return stdout;
    }
  }

  public ProcessStreamReader getStandardErrorReader() {
    synchronized (exitValue) {
      return stderr;
    }
  }

  private void waitForProcessStart() throws InterruptedException, TimeoutException {
    final long start = System.currentTimeMillis();
    boolean done = false;
    while (!done) {
      synchronized (exitValue) {
        done = (process != null || processException != null)
            && (started || exitValue.get() > -1 || interrupted);
      }
      if (!done && System.currentTimeMillis() > start + timeoutMillis) {
        throw new TimeoutException("Timed out launching process");
      }
      Thread.sleep(DELAY);
    }
  }

  public boolean isAlive() throws InterruptedException, TimeoutException {
    checkStarting();
    waitForProcessStart();

    synchronized (exitValue) {
      if (interrupted) {
        throw new InterruptedException("Process was interrupted");
      }
      return exitValue.get() == -1 && started && !stopped && !interrupted
          && processThread.isAlive();
    }
  }

  public ProcessWrapper destroy() {
    if (process != null) {
      process.destroy();
    }
    return this;
  }

  public int waitFor(final long timeout, final boolean throwOnTimeout) throws InterruptedException {
    checkStarting();
    final Thread thread = getThread();
    thread.join(timeout);
    synchronized (exitValue) {
      if (throwOnTimeout) {
        checkStopped();
      }
      return exitValue.get();
    }
  }

  public int waitFor(final long timeout) throws InterruptedException {
    return waitFor(timeout, false);
  }

  public int waitFor(final boolean throwOnTimeout) throws InterruptedException {
    return waitFor(timeoutMillis, throwOnTimeout);
  }

  public int waitFor() throws InterruptedException {
    return waitFor(timeoutMillis, false);
  }

  public String getOutput() {
    return getOutput(false);
  }

  public String getOutput(final boolean ignoreStopped) {
    checkStarting();
    if (!ignoreStopped) {
      checkStopped();
    }
    final StringBuffer sb = new StringBuffer();
    final Iterator<String> iterator = allLines.iterator();
    while (iterator.hasNext()) {
      sb.append(iterator.next() + System.lineSeparator());
    }
    return sb.toString();
  }

  public ProcessWrapper sendInput() {
    checkStarting();
    sendInput("");
    return this;
  }

  public ProcessWrapper sendInput(final String input) {
    checkStarting();
    final PrintStream ps = new PrintStream(process.getOutputStream());
    ps.println(input);
    ps.flush();
    return this;
  }

  public ProcessWrapper failIfOutputMatches(final String patternString, final long timeoutMillis)
      throws InterruptedException {
    checkStarting();
    checkOk();

    final Pattern pattern = Pattern.compile(patternString);
    logger.debug("failIfOutputMatches waiting for \"{}\"...", patternString);
    final long start = System.currentTimeMillis();

    while (System.currentTimeMillis() <= start + timeoutMillis) {
      final String line = lineBuffer.poll(timeoutMillis, MILLISECONDS);
      if (line != null && pattern.matcher(line).matches()) {
        fail("failIfOutputMatches Matched pattern \"" + patternString + "\" against output \""
            + line + "\". Output: " + allLines);
      }
    }
    return this;
  }

  /*
   * Waits for the process stdout or stderr stream to contain the specified text. Uses the specified
   * timeout for debugging purposes.
   */
  public ProcessWrapper waitForOutputToMatch(final String patternString, final long timeoutMillis)
      throws InterruptedException {
    checkStarting();
    checkOk();

    logger.debug("ProcessWrapper:waitForOutputToMatch waiting for \"{}\"...", patternString);
    final Pattern pattern = Pattern.compile(patternString);

    while (true) {
      final String line = lineBuffer.poll(timeoutMillis, MILLISECONDS);
      if (line == null) {
        fail("Timed out waiting for output \"" + patternString + "\" after " + timeoutMillis +
            " ms from process \"" + toString(process) + "\" in \"" + this + "\". Output: " +
            new OutputFormatter(allLines));
      }

      if (pattern.matcher(line).matches()) {
        logger.debug(
            "ProcessWrapper:waitForOutputToMatch Matched pattern \"{}\" against output \"{}\"",
            patternString, line);
        break;
      }
      logger.debug(
          "ProcessWrapper:waitForOutputToMatch Did not match pattern \"{}\" against output \"{}\"",
          patternString, line);
    }
    return this;
  }

  private String toString(Process process) {
    StringBuilder sb = new StringBuilder(process.getClass().getSimpleName());
    sb.append("@").append(System.identityHashCode(this)).append("{");
    sb.append("alive=").append(process.isAlive());
    sb.append("}");
    return sb.toString();
  }

  /*
   * Waits for the process stdout or stderr stream to contain the specified text. Uses the default
   * timeout.
   */
  public ProcessWrapper waitForOutputToMatch(final String patternString)
      throws InterruptedException {
    return waitForOutputToMatch(patternString, timeoutMillis);
  }

  public ProcessWrapper execute() throws InterruptedException, TimeoutException {
    return execute(null, directory);
  }

  public ProcessWrapper execute(final Properties properties)
      throws InterruptedException, TimeoutException {
    return execute(properties, directory);
  }

  public ProcessWrapper execute(final Properties properties, final File workingDirectory)
      throws InterruptedException, TimeoutException {
    synchronized (exitValue) {
      if (starting) {
        throw new IllegalStateException("ProcessWrapper can only be executed once");
      }
      starting = true;
      processThread =
          new Thread(() -> start(properties, workingDirectory), "ProcessWrapper Process Thread");
    }
    processThread.start();

    waitForProcessStart();

    synchronized (exitValue) {
      if (processException != null) {
        logger.error("ProcessWrapper:execute failed with " + processException);
        processException.printStackTrace();
      }
    }

    if (useMainLauncher) {
      // to trigger MainLauncher delegation to inner main
      sendInput();
    }
    return this;
  }

  private void start(final Properties properties, final File workingDirectory) {
    final List<String> jvmArgumentsList = new ArrayList<>();

    if (properties != null) {
      for (Map.Entry<Object, Object> entry : properties.entrySet()) {
        if (!entry.getKey().equals(LOG_FILE)) {
          jvmArgumentsList.add("-D" + entry.getKey() + "=" + entry.getValue());
        }
      }
    }

    if (headless) {
      jvmArgumentsList.add("-Djava.awt.headless=true");
    }

    if (jvmArguments != null) {
      Collections.addAll(jvmArgumentsList, jvmArguments);
    }

    try {
      synchronized (exitValue) {
        final String[] command =
            defineCommand(jvmArgumentsList.toArray(new String[jvmArgumentsList.size()]),
                workingDirectory.getCanonicalPath());
        process = new ProcessBuilder(command).directory(workingDirectory).start();

        final StringBuilder processCommand = new StringBuilder();
        boolean addSpace = false;

        for (String string : command) {
          if (addSpace) {
            processCommand.append(" ");
          }
          processCommand.append(string);
          addSpace = true;
        }

        final String commandString = processCommand.toString();
        logger.info("Starting " + commandString);

        final ProcessStreamReader stdOut = new ProcessStreamReader(commandString,
            process.getInputStream(), this);
        final ProcessStreamReader stdErr = new ProcessStreamReader(commandString,
            process.getErrorStream(), this);

        stdout = stdOut;
        stderr = stdErr;
        outputReader = new ProcessOutputReader(process, stdOut, stdErr);
        started = true;
      }

      outputReader.start();
      outputReader.waitFor(PROCESS_TIMEOUT_MILLIS, MILLISECONDS);
      boolean exited = process.waitFor(PROCESS_TIMEOUT_MILLIS, MILLISECONDS);

      synchronized (exitValue) {
        exitValue.set(exited ? process.exitValue() : 0);
        stopped = exited;
      }

    } catch (InterruptedException e) {
      synchronized (exitValue) {
        interrupted = true;
        processException = e;
      }
    } catch (Throwable t) {
      synchronized (exitValue) {
        processException = t;
      }
    }
  }

  private String[] defineCommand(final String[] jvmArguments, String workingDir)
      throws IOException {
    final File javaBinDir = new File(System.getProperty("java.home"), "bin");
    final File javaExe = new File(javaBinDir, "java");

    String classPath = System.getProperty("java.class.path");
    List<String> parts = Arrays.asList(classPath.split(File.pathSeparator));
    String manifestJar = createManifestJar(parts, workingDir);

    final List<String> argumentList = new ArrayList<>();
    argumentList.add(javaExe.getPath());
    argumentList.add("-classpath");
    argumentList.add(manifestJar);

    // -d64 is not a valid option for windows and results in failure
    // -d64 is not a valid option for java 9 and above
    final int bits = Integer.getInteger("sun.arch.data.model", 0);
    if (bits == 64 && !System.getProperty("os.name").toLowerCase().contains("windows")
        && !SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9)) {
      argumentList.add("-d64");
    }

    argumentList.add("-Djava.library.path=" + System.getProperty("java.library.path"));

    if (jvmArguments != null) {
      argumentList.addAll(Arrays.asList(jvmArguments));
    }

    if (useMainLauncher) {
      argumentList.add(MainLauncher.class.getName());
    }
    argumentList.add(mainClass.getName());

    if (mainArguments != null) {
      argumentList.addAll(Arrays.asList(mainArguments));
    }

    return argumentList.toArray(new String[0]);
  }

  private void checkStarting() throws IllegalStateException {
    synchronized (exitValue) {
      if (!starting) {
        throw new IllegalStateException("Process has not been launched");
      }
    }
  }

  private void checkStopped() throws IllegalStateException {
    synchronized (exitValue) {
      if (!stopped) {
        throw new IllegalStateException("Process has not stopped");
      }
    }
  }

  private void checkOk() throws RuntimeException {
    if (processException != null) {
      throw new RuntimeException("Failed to launch process", processException);
    }
  }

  private Thread getThread() {
    synchronized (exitValue) {
      return processThread;
    }
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder(getClass().getSimpleName());
    sb.append("@").append(System.identityHashCode(this)).append("{");
    sb.append("mainClass=").append(mainClass).append(", ");
    sb.append("jvmArguments=").append(Arrays.toString(jvmArguments)).append(", ");
    sb.append("mainArguments=").append(Arrays.toString(mainArguments));
    sb.append("}");
    return sb.toString();
  }

  public Process getProcess() {
    return process;
  }

  /**
   * Method to create a manifest jar from a list of jars or directories. The provided entries are
   * first converted to absolute paths and then converted to relative paths, relative to the
   * location provided. This is to support the Manifest's requirement that class-paths only be
   * relative. For example, if a jar is given as /a/b/c/foo.jar and the location is /tmp/app, the
   * following will happen:
   * - the manifest jar will be created as /tmp/app/manifest.jar
   * - the class-path attribute will be ../../a/b/c/foo.jar
   *
   * @return the path to the created manifest jar
   */
  public static String createManifestJar(List<String> entries, String location) throws IOException {
    // Must use the canonical path so that symbolic links are resolved correctly
    Path locationPath = new File(location).getCanonicalFile().toPath();
    Files.createDirectories(locationPath);

    List<String> manifestEntries = new ArrayList<>();
    for (String jarEntry : entries) {
      Path jarEntryAbsolutePath = Paths.get(jarEntry).toAbsolutePath();
      Path jarEntryRelativizedPath = locationPath.relativize(jarEntryAbsolutePath);
      if (jarEntryAbsolutePath.toFile().isDirectory()) {
        manifestEntries.add(jarEntryRelativizedPath + File.separator);
      } else {
        manifestEntries.add(jarEntryRelativizedPath.toString());
      }
    }

    Manifest manifest = new Manifest();
    Attributes attributes = manifest.getMainAttributes();
    attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
    attributes.put(new Attributes.Name("Class-Path"), String.join(" ", manifestEntries));

    // Generate a 'unique' 8 char name
    String uuid = UUID.randomUUID().toString().substring(0, 8);
    Path manifestJarPath = Paths.get(location, "manifest-" + uuid + ".jar");
    File manifestJarFile = manifestJarPath.toFile();
    manifestJarFile.deleteOnExit();

    try (JarOutputStream jos =
        new JarOutputStream(new FileOutputStream(manifestJarFile), manifest)) {
      // the above try-with-resource writes the manifest to the manifestJarFile
    }

    return manifestJarPath.toFile().getAbsolutePath();
  }

  public static class Builder {

    private String[] jvmArguments;
    private Class<?> mainClass;
    private String[] mainArguments;
    private boolean useMainLauncher = true;
    private boolean headless = true;
    private long timeoutMillis = PROCESS_TIMEOUT_MILLIS;
    private boolean inline;
    private File directory = new File(System.getProperty("user.dir"));

    public Builder jvmArguments(final String[] jvmArguments) {
      this.jvmArguments = jvmArguments;
      return this;
    }

    public Builder mainClass(final Class<?> mainClass) {
      this.mainClass = mainClass;
      return this;
    }

    public Builder mainArguments(final String[] mainArguments) {
      this.mainArguments = mainArguments;
      return this;
    }

    public Builder useMainLauncher(final boolean useMainLauncher) {
      this.useMainLauncher = useMainLauncher;
      return this;
    }

    public Builder headless(final boolean headless) {
      this.headless = headless;
      return this;
    }

    public Builder timeoutMillis(final long timeoutMillis) {
      this.timeoutMillis = timeoutMillis;
      return this;
    }

    public Builder inline(final boolean inline) {
      this.inline = inline;
      return this;
    }

    public Builder directory(final File directory) {
      this.directory = directory;
      return this;
    }

    public ProcessWrapper build() {
      return new ProcessWrapper(jvmArguments, mainClass, mainArguments, useMainLauncher, headless,
          timeoutMillis, directory);
    }
  }
}
