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

import static java.lang.System.lineSeparator;
import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;

import org.apache.geode.internal.process.ProcessStreamReader.ReadingMode;
import org.apache.geode.internal.util.StopWatch;

/**
 * Abstract base class for functional integration testing of {@link ProcessStreamReader}.
 */
public abstract class AbstractProcessStreamReaderIntegrationTest {

  /** Timeout to join to a running ProcessStreamReader thread */
  private static final int READER_JOIN_TIMEOUT_MILLIS = 2 * 60 * 1000;

  /** Sleep timeout for {@link ProcessSleeps} instead of sleeping Long.MAX_VALUE */
  private static final int PROCESS_FAIL_SAFE_TIMEOUT_MILLIS = 8 * 60 * 1000;

  /** Additional time for launched processes to live before terminating */
  private static final int PROCESS_TIME_TO_LIVE_MILLIS = 3 * 500;

  protected Process process;
  protected ProcessStreamReader stderr;
  protected ProcessStreamReader stdout;

  private StringBuffer stdoutBuffer;
  private StringBuffer stderrBuffer;

  @Before
  public void setUpAbstractProcessStreamReaderIntegrationTest() {
    stdoutBuffer = new StringBuffer();
    stderrBuffer = new StringBuffer();
  }

  @After
  public void afterProcessStreamReaderTestCase() throws Exception {
    if (stderr != null) {
      stderr.stop();
    }
    if (stdout != null) {
      stdout.stop();
    }
    if (process != null) {
      try {
        process.getErrorStream().close();
        process.getInputStream().close();
        process.getOutputStream().close();
      } finally {
        // this is async and can require more than 10 seconds on slower machines
        process.destroy();
      }
    }
  }

  protected abstract ReadingMode getReadingMode();

  protected void assertThatProcessAndReadersStopped() throws InterruptedException {
    assertThatProcessAndReadersStoppedWithExitValue(0);
  }

  protected void assertThatProcessAndReadersStoppedWithExitValue(final int exitValue)
      throws InterruptedException {
    assertThat(process.exitValue()).isEqualTo(exitValue);
    assertThat(stdout.join(READER_JOIN_TIMEOUT_MILLIS).isRunning()).isFalse();
    assertThat(stderr.join(READER_JOIN_TIMEOUT_MILLIS).isRunning()).isFalse();
  }

  protected void assertThatProcessAndReadersDied() throws InterruptedException {
    assertThat(process.isAlive()).isFalse();
    assertThat(stdout.join(READER_JOIN_TIMEOUT_MILLIS).isRunning()).isFalse();
    assertThat(stderr.join(READER_JOIN_TIMEOUT_MILLIS).isRunning()).isFalse();
  }

  protected void assertThatProcessIsAlive(final Process process) {
    assertThat(process.isAlive()).isTrue();
  }

  protected void assertThatStdErrContains(final String value) {
    assertThat(stderrBuffer.toString()).contains(value);
  }

  protected void assertThatStdErrContainsExactly(final String value) {
    assertThat(stderrBuffer.toString()).isEqualTo(value);
  }

  protected void assertThatStdOutContainsExactly(final String value) {
    assertThat(stdoutBuffer.toString()).isEqualTo(value);
  }

  protected void givenRunningProcessWithStreamReaders(final Class<?> mainClass) {
    givenStartedProcess(mainClass);

    assertThat(process.isAlive()).isTrue();

    await().untilAsserted(() -> assertThat(stdout.isRunning()).isTrue());
    await().untilAsserted(() -> assertThat(stderr.isRunning()).isTrue());
  }

  private void givenStartedProcess(final Class<?> mainClass) {
    try {
      process = new ProcessBuilder(createCommandLine(mainClass)).start();
      stdout = buildProcessStreamReader(process.getInputStream(), getReadingMode());
      stderr = buildProcessStreamReader(process.getErrorStream(), getReadingMode());
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }

  protected void givenStartedProcessWithStreamListeners(final Class<?> mainClass) {
    try {
      process = new ProcessBuilder(createCommandLine(mainClass)).start();
      stdout = buildProcessStreamReader(process.getInputStream(), getReadingMode(), stdoutBuffer);
      stderr = buildProcessStreamReader(process.getErrorStream(), getReadingMode(), stderrBuffer);
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }

  protected static String[] createCommandLine(final Class<?> clazz) {
    List<String> commandLine = new ArrayList<>();

    commandLine.add(getJavaPath());
    commandLine.add("-server");
    commandLine.add("-classpath");
    commandLine.add(getClassPath());
    commandLine.add("-D" + "java.awt.headless=true");
    commandLine.add(clazz.getName());

    return commandLine.toArray(new String[commandLine.size()]);
  }

  protected void waitUntilProcessStops() {
    await().untilAsserted(() -> assertThat(isProcessAlive(process)).isFalse());
  }

  protected void waitUntilProcessStops(final long timeout, final TimeUnit unit) {
    await()
        .untilAsserted(() -> assertThat(isProcessAlive(process)).isFalse());
  }

  private ProcessStreamReader buildProcessStreamReader(final InputStream stream,
      final ReadingMode mode) {
    return new ProcessStreamReader.Builder(process).inputStream(stream).readingMode(mode).build()
        .start();
  }

  private ProcessStreamReader buildProcessStreamReader(final InputStream stream,
      final ReadingMode mode, final StringBuffer buffer) {
    ProcessStreamReader.Builder builder =
        new ProcessStreamReader.Builder(process).inputStream(stream).readingMode(mode);
    if (buffer != null) {
      builder.inputListener(buffer::append);
    }
    return builder.build().start();
  }

  private static String getClassPath() {
    return System.getProperty("java.class.path");
  }

  private static String getJavaPath() {
    String java = "java";
    return new File(new File(System.getProperty("java.home"), "bin"), java).getPath();
  }

  private static void sleepAtMost(final int duration) throws InterruptedException {
    StopWatch stopWatch = new StopWatch(true);
    while (stopWatch.elapsedTimeMillis() < duration) {
      Thread.sleep(1000);
    }
  }

  /**
   * Class with main that sleeps until destroyed.
   */
  protected static class ProcessSleeps {
    public static void main(final String... args) throws InterruptedException {
      sleepAtMost(PROCESS_FAIL_SAFE_TIMEOUT_MILLIS);
    }
  }

  /**
   * Class with main that throws Error.
   */
  protected static class ProcessThrowsError {
    private static final String[] LINES =
        new String[] {"ProcessThrowsError is starting" + lineSeparator(),
            "ProcessThrowsError is sleeping" + lineSeparator(),
            "ProcessThrowsError is throwing" + lineSeparator()};

    protected static final String STDOUT = "";

    protected static final String ERROR_MSG = "ProcessThrowsError throws Error";

    public static void main(final String... args) throws InterruptedException {
      System.err.print(LINES[0]);
      System.err.print(LINES[1]);
      sleepAtMost(PROCESS_TIME_TO_LIVE_MILLIS);
      System.err.print(LINES[2]);
      throw new Error(ERROR_MSG);
    }
  }

  /**
   * Class with main that prints to stdout and sleeps.
   */
  protected static class ProcessPrintsToStdout {
    private static final String[] LINES =
        new String[] {"ProcessPrintsToStdout is starting" + lineSeparator(),
            "ProcessPrintsToStdout is sleeping" + lineSeparator(),
            "ProcessPrintsToStdout is exiting" + lineSeparator()};

    protected static final String STDOUT =
        new StringBuilder().append(LINES[0]).append(LINES[1]).append(LINES[2]).toString();

    protected static final String STDERR = "";

    public static void main(final String... args) throws InterruptedException {
      System.out.print(LINES[0]);
      System.out.print(LINES[1]);
      sleepAtMost(PROCESS_TIME_TO_LIVE_MILLIS);
      System.out.print(LINES[2]);
    }
  }

  /**
   * Class with main that prints to stderr and sleeps.
   */
  protected static class ProcessPrintsToStderr {
    private static final String[] LINES =
        new String[] {"ProcessPrintsToStdout is starting" + lineSeparator(),
            "ProcessPrintsToStdout is sleeping" + lineSeparator(),
            "ProcessPrintsToStdout is exiting" + lineSeparator()};

    protected static final String STDOUT = "";

    protected static final String STDERR =
        new StringBuilder().append(LINES[0]).append(LINES[1]).append(LINES[2]).toString();

    public static void main(final String... args) throws InterruptedException {
      System.err.print(LINES[0]);
      System.err.print(LINES[1]);
      sleepAtMost(PROCESS_TIME_TO_LIVE_MILLIS);
      System.err.print(LINES[2]);
    }
  }

  /**
   * Class with main that prints to both stdout and stderr and sleeps.
   */
  protected static class ProcessPrintsToBoth {
    private static final String[] OUT_LINES =
        new String[] {"ProcessPrintsToBoth(out) is starting" + lineSeparator(),
            "ProcessPrintsToBoth(out) is sleeping" + lineSeparator(),
            "ProcessPrintsToBoth(out) is exiting" + lineSeparator()};

    private static final String[] ERR_LINES =
        new String[] {"ProcessPrintsToBoth(err) is starting" + lineSeparator(),
            "ProcessPrintsToBoth(err) is sleeping" + lineSeparator(),
            "ProcessPrintsToBoth(err) is exiting" + lineSeparator()};

    protected static final String STDOUT = new StringBuilder().append(OUT_LINES[0])
        .append(OUT_LINES[1]).append(OUT_LINES[2]).toString();

    protected static final String STDERR = new StringBuilder().append(ERR_LINES[0])
        .append(ERR_LINES[1]).append(ERR_LINES[2]).toString();

    public static void main(final String... args) throws InterruptedException {
      System.out.print(OUT_LINES[0]);
      System.err.print(ERR_LINES[0]);
      System.out.print(OUT_LINES[1]);
      System.err.print(ERR_LINES[1]);
      sleepAtMost(PROCESS_TIME_TO_LIVE_MILLIS);
      System.out.print(OUT_LINES[2]);
      System.err.print(ERR_LINES[2]);
    }
  }
}
