// Copyright 2011 Google Inc. All Rights Reserved.
//
// 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 adaptorlib.prebuilt;

import adaptorlib.DocumentTransform;
import adaptorlib.IOHelper;
import adaptorlib.TransformException;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * A conduit that allows a simple way to create a document transform based on
 * a command line program.
 */
public class CommandLineTransform extends DocumentTransform {

  private static final int STDERR_BUFFER_SIZE = 51200; // 50 kB

  public CommandLineTransform(String name) {
    super(name);
  }

  @Override
  public void transform(ByteArrayOutputStream contentIn, ByteArrayOutputStream metadataIn,
                        OutputStream contentOut, OutputStream metadataOut,
                        Map<String, String> params) throws TransformException, IOException {
    // Java Processes can only take input on 1 channel, stdin. If we want
    // to have two separate channels, we would need to either:
    // - Have two separate commands that get called for content and metadata
    // - Write metadata to file and send filename as parameter.
    // - Send them both in through stdin with some separator.
    //
    // We don't yet support sending metadata with content, so this version of
    // CommandLineTransform only handles the content. In the case of HTML, the
    // metadata is baked in anyway.

    List<String> command = Arrays.asList(transformCommand.split(" "));
    if (commandAcceptsParameters) {
      for (Map.Entry<String, String> param : params.entrySet()) {
        command.add("-" + param.getKey());
        command.add(param.getValue());
      }
    }

    ProcessBuilder pb = new ProcessBuilder(command);
    pb.redirectErrorStream(false);  // We want 2 streams to come out for stdout and stderr.
    if (workingDirectory != null && !workingDirectory.isEmpty()) {
      pb.directory(new File(workingDirectory));
    }

    Process p = pb.start();

    // Streams can be confusing because an input to one component is an output
    // to another based on the frame of reference.
    // Here, stdin is an OutputStream, because we write to it.
    // stdout and stderr are InputStreams, because we read from them.
    OutputStream stdin = p.getOutputStream();
    InputStream stdout = p.getInputStream();
    InputStream stderr = p.getErrorStream();

    try {
      // Run it
      contentIn.writeTo(stdin);
      stdin.close();  // Necessary for some commands that expect EOF.
      int exitCode = p.waitFor();

      // Handle stderr
      if (exitCode != 0 || stderr.available() > 0) {
        byte[] buf = new byte[STDERR_BUFFER_SIZE];
        stderr.read(buf);
        throw new TransformException(new String(buf));
      }

      // Copy stdout
      IOHelper.copyStream(stdout, contentOut);
    } catch (InterruptedException e) {
      throw new TransformException(e);
    } finally {
      stdin.close();
      stdout.close();
      stderr.close();
      p.destroy();
    }
  }

  /**
   * This controls whether the input parameters to the transform call are passed
   * along to the actual call to the command. This is useful in the case where a
   * binary might return erros when unexpected command line flags are passed in.
   */
  public void commandAcceptsParameters(boolean commandAcceptsParameters) {
    this.commandAcceptsParameters = commandAcceptsParameters;
  }

  public boolean commandAcceptsParameters() {
    return commandAcceptsParameters;
  }

  /**
   * Sets the command that is in charge of transforming the document content.
   * This command should take input on stdin, and print the output to stdout.
   * Transform parameters are sent on the command line as flags.
   *    e.g. /path/to/command -param1 value1 -param2 value2 ...
   *
   * Errors should be printed to stderr. If anything is printed to stderr, it
   * will cause a failure for this transform operation.
   */
  public void transformCommand(String transformCommand) {
    this.transformCommand = transformCommand;
  }

  /**
   * Sets the working directory. Must be valid.
   * @return true on success.
   */
  public boolean workingDirectory(String dir) {
    File file = new File(dir);
    if (file.isDirectory()) {
      workingDirectory = dir;
      return true;
    }
    return false;
  }

  /**
   * @return The working directory for the command line process.
   */
  public String workingDirectory() {
    return workingDirectory;
  }

  private boolean commandAcceptsParameters = true;
  private String transformCommand = "";
  private String workingDirectory = null;
}
