package org.apache.helix;

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

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Wrapper for running commands outside of the JVM
 * @see {@link Process}
 */
public class ExternalCommand {
  public static final String MODULE = ExternalCommand.class.getName();
  public static final Logger LOG = LoggerFactory.getLogger(MODULE);

  private final ProcessBuilder _processBuilder;

  private Process _process;
  private InputReader _out;
  private InputReader _err;

  /**
   * Stream redirector
   */
  private static class InputReader extends Thread {
    private static final int BUFFER_SIZE = 2048;

    private final InputStream _in;
    private final ByteArrayOutputStream _out;
    private boolean _running = false;

    InputReader(InputStream in) {
      _in = in;
      _out = new ByteArrayOutputStream();
    }

    @Override
    public void run() {
      _running = true;

      byte[] buf = new byte[BUFFER_SIZE];
      int n = 0;
      try {
        while ((n = _in.read(buf)) != -1)
          _out.write(buf, 0, n);
      } catch (IOException e) {
        LOG.error("error while reading external command", e);
      }

      _running = false;
    }

    public byte[] getOutput() {
      if (_running)
        throw new IllegalStateException("wait for process to be completed");

      return _out.toByteArray();
    }
  }

  /**
   * Initialize with a {@link ProcessBuilder}
   * @param processBuilder initialized {@link ProcessBuilder} object
   */
  public ExternalCommand(ProcessBuilder processBuilder) {
    _processBuilder = processBuilder;
  }

  /**
   * After creating the command, you have to start it...
   * @throws IOException
   */
  public void start() throws IOException {
    _process = _processBuilder.start();
    _out = new InputReader(new BufferedInputStream(_process.getInputStream()));
    _err = new InputReader(new BufferedInputStream(_process.getErrorStream()));

    _out.start();
    _err.start();
  }

  /**
   * @see {@link ProcessBuilder#environment()}
   */
  public Map<String, String> getEnvironment() {
    return _processBuilder.environment();
  }

  /**
   * @see {@link ProcessBuilder#directory()}
   */
  public File getWorkingDirectory() {
    return _processBuilder.directory();
  }

  /**
   * @see {@link ProcessBuilder#directory(File)}
   */
  public void setWorkingDirectory(File directory) {
    _processBuilder.directory(directory);
  }

  /**
   * @see {@link ProcessBuilder#redirectErrorStream()}
   */
  public boolean getRedirectErrorStream() {
    return _processBuilder.redirectErrorStream();
  }

  /**
   * @see {@link ProcessBuilder#redirectErrorStream(boolean)}
   */
  public void setRedirectErrorStream(boolean redirectErrorStream) {
    _processBuilder.redirectErrorStream(redirectErrorStream);
  }

  /**
   * Get the contents of the output stream after completion
   * @return bytes from the output stream
   * @throws InterruptedException the process was interrupted before completion
   */
  public byte[] getOutput() throws InterruptedException {
    waitFor();
    return _out.getOutput();
  }

  /**
   * Get the contents of the error stream after completion
   * @return bytes from the error stream
   * @throws InterruptedException the process was interrupted before completion
   */
  public byte[] getError() throws InterruptedException {
    waitFor();
    return _err.getOutput();
  }

  /**
   * Returns the output as a string.
   * @param encoding string encoding scheme, e.g. "UTF-8"
   * @return encoded string
   * @throws InterruptedException the process was interrupted before completion
   * @throws UnsupportedEncodingException the encoding scheme is invalid
   */
  public String getStringOutput(String encoding) throws InterruptedException,
      UnsupportedEncodingException {
    return new String(getOutput(), encoding);
  }

  /**
   * Returns the output as a string. Uses encoding "UTF-8".
   * @return utf8 encoded string
   * @throws InterruptedException the process was interrupted before completion
   */
  public String getStringOutput() throws InterruptedException {
    try {
      return getStringOutput("UTF-8");
    } catch (UnsupportedEncodingException e) {
      // should not happen
      throw new RuntimeException(e);
    }
  }

  /**
   * Returns the error as a string.
   * @param encoding the encoding scheme, e.g. "UTF-8"
   * @return error as string
   * @throws InterruptedException the process was interrupted before completion
   * @throws UnsupportedEncodingException the encoding scheme is invalid
   */
  public String getStringError(String encoding) throws InterruptedException,
      UnsupportedEncodingException {
    return new String(getError(), encoding);
  }

  /**
   * Returns the error as a string. Uses encoding "UTF-8".
   * @return error as string
   * @throws InterruptedException the process was interrupted before completion
   */
  public String getStringError() throws InterruptedException {
    try {
      return getStringError("UTF-8");
    } catch (UnsupportedEncodingException e) {
      // should not happen
      throw new RuntimeException(e);
    }
  }

  /**
   * Properly waits until everything is complete: joins on the thread that
   * reads the output, joins on the thread that reads the error and finally
   * wait for the process to be finished.
   * @return the status code of the process.
   * @throws InterruptedException the process was interrupted before completion
   */
  public int waitFor() throws InterruptedException {
    if (_process == null)
      throw new IllegalStateException("you must call start first");

    _out.join();
    _err.join();
    return _process.waitFor();
  }

  /**
   * Properly waits until everything is complete: joins on the thread that
   * reads the output, joins on the thread that reads the error and finally
   * wait for the process to be finished.
   * If the process has not completed before the timeout, throws a {@link TimeoutException}
   * @return the status code of the process.
   * @throws TimeoutException the process timed out
   * @throws InterruptedException the process was interrupted before completion
   */
  public int waitFor(long timeout) throws InterruptedException, TimeoutException {
    if (_process == null)
      throw new IllegalStateException("you must call start first");

    // Chronos c = new Chronos();
    _out.join(timeout);
    // timeout -= c.tick();
    if (timeout <= 0)
      throw new TimeoutException("Wait timed out");
    _err.join(timeout);
    // timeout -= c.tick();
    if (timeout <= 0)
      throw new TimeoutException("Wait timed out");

    // there is no timeout in this API, not much we can do here
    // waiting on the other two threads should give us some safety
    return _process.waitFor();
  }

  /**
   * @see {@link Process#exitValue()}
   * @return the return code of the process
   */
  public int exitValue() {
    if (_process == null)
      throw new IllegalStateException("you must call start first");

    return _process.exitValue();
  }

  /**
   * see {@link Process#destroy()}
   */
  public void destroy() {
    if (_process == null)
      throw new IllegalStateException("you must call start first");

    _process.destroy();
  }

  /**
   * Creates an external process from the command. It is not started and you have to call
   * start on it!
   * @param commands the command to execute
   * @return the process
   */
  public static ExternalCommand create(String... commands) {
    ExternalCommand ec = new ExternalCommand(new ProcessBuilder(commands));
    return ec;
  }

  /**
   * Creates an external process from the command. It is not started and you have to call
   * start on it!
   * @param commands the command to execute
   * @return the process
   */
  public static ExternalCommand create(List<String> commands) {
    ExternalCommand ec = new ExternalCommand(new ProcessBuilder(commands));
    return ec;
  }

  /**
   * Creates an external process from the command. The command is executed.
   * @param commands the commands to execute
   * @return the process
   * @throws IOException if there is an error
   */
  public static ExternalCommand start(String... commands) throws IOException {
    ExternalCommand ec = new ExternalCommand(new ProcessBuilder(commands));
    ec.start();
    return ec;
  }

  /**
   * Executes the external command in the given working directory and waits for it to be
   * finished.
   * @param workingDirectory the root directory from where to run the command
   * @param command the command to execute (should be relative to the working directory
   * @param args the arguments to the command
   * @return the process
   */
  public static ExternalCommand execute(File workingDirectory, String command, String... args)
      throws IOException, InterruptedException {
    try {
      return executeWithTimeout(workingDirectory, command, 0, args);
    } catch (TimeoutException e) {
      // Can't happen!
      throw new IllegalStateException(MODULE + ".execute: Unexpected timeout occurred!");
    }
  }

  /**
   * Executes the external command in the given working directory and waits (until timeout
   * is elapsed) for it to be finished.
   * @param workingDirectory
   *          the root directory from where to run the command
   * @param command
   *          the command to execute (should be relative to the working directory
   * @param timeout
   *          the maximum amount of time to wait for this external command (in ms). If
   *          this value is less than or equal to 0, timeout is ignored
   * @param args
   *          the arguments to the command
   * @return the process
   */
  public static ExternalCommand executeWithTimeout(File workingDirectory, String command,
      long timeout, String... args) throws IOException, InterruptedException, TimeoutException {
    List<String> arguments = new ArrayList<String>(args.length + 1);

    arguments.add(new File(workingDirectory, command).getAbsolutePath());
    arguments.addAll(Arrays.asList(args));

    ExternalCommand cmd = ExternalCommand.create(arguments);

    cmd.setWorkingDirectory(workingDirectory);

    cmd.setRedirectErrorStream(true);

    cmd.start();

    /* Use timeout if it is a valid value! */
    if (timeout <= 0)
      cmd.waitFor();
    else
      cmd.waitFor(timeout);

    if (LOG.isDebugEnabled())
      LOG.debug(cmd.getStringOutput());

    return cmd;
  }
}
