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

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Creates operating system processes.
 *
 * @since 1.5
 */
public final class ProcessBuilder {

    private List<String> command;

    private File directory;

    private Map<String, String> environment;

    private boolean redirectErrorStream;

    /**
     * Constructs a new {@code ProcessBuilder} instance with the specified
     * operating system program and its arguments.
     * 
     * @param command
     *            the requested operating system program and its arguments.
     */
    public ProcessBuilder(String... command) {
        this(toList(command));
    }

    /**
     * Constructs a new {@code ProcessBuilder} instance with the specified
     * operating system program and its arguments. Note that the list passed to
     * this constructor is not copied, so any subsequent updates to it are
     * reflected in this instance's state.
     * 
     * @param command
     *            the requested operating system program and its arguments.
     * @throws NullPointerException
     *             if {@code command} is {@code null}.
     */
    public ProcessBuilder(List<String> command) {
        super();
        if (command == null) {
            throw new NullPointerException();
        }
        this.command = command;
        this.environment = new org.apache.harmony.luni.platform.Environment.EnvironmentMap(
                System.getenv());
    }

    /**
     * Returns this process builder's current program and arguments. Note that
     * the returned list is not a copy and modifications to it will change the
     * state of this instance.
     *
     * @return this process builder's program and arguments.
     */
    public List<String> command() {
        return command;
    }

    /**
     * Changes the program and arguments of this process builder.
     * 
     * @param command
     *            the new operating system program and its arguments.
     * @return this process builder instance.
     */
    public ProcessBuilder command(String... command) {
        return command(toList(command));
    }

    /**
     * Changes the program and arguments of this process builder. Note that the
     * list passed to this method is not copied, so any subsequent updates to it
     * are reflected in this instance's state.
     *
     * @param command
     *            the new operating system program and its arguments.
     * @return this process builder instance.
     * @throws NullPointerException
     *             if {@code command} is {@code null}.
     */
    public ProcessBuilder command(List<String> command) {
        if (command == null) {
            throw new NullPointerException();
        }
        this.command = command;
        return this;
    }

    /**
     * Returns the working directory of this process builder. If {@code null} is
     * returned, then the working directory of the Java process is used when a
     * process is started.
     * 
     * @return the current working directory, may be {@code null}.
     */
    public File directory() {
        return directory;
    }

    /**
     * Changes the working directory of this process builder. If the specified
     * directory is {@code null}, then the working directory of the Java
     * process is used when a process is started.
     *
     * @param directory
     *            the new working directory for this process builder.
     * @return this process builder instance.
     */
    public ProcessBuilder directory(File directory) {
        this.directory = directory;
        return this;
    }

    /**
     * Returns this process builder's current environment. When a process
     * builder instance is created, the environment is populated with a copy of
     * the environment, as returned by {@link System#getenv()}. Note that the
     * map returned by this method is not a copy and any changes made to it are
     * reflected in this instance's state.
     *
     * @return the map containing this process builder's environment variables.
     */
    public Map<String, String> environment() {
        return environment;
    }

    /**
     * Indicates whether the standard error should be redirected to standard
     * output. If redirected, the {@link Process#getErrorStream()} will always
     * return end of stream and standard error is written to
     * {@link Process#getInputStream()}.
     *
     * @return {@code true} if the standard error is redirected; {@code false}
     *         otherwise.
     */
    public boolean redirectErrorStream() {
        return redirectErrorStream;
    }

    /**
     * Changes the state of whether or not standard error is redirected to
     * standard output.
     * 
     * @param redirectErrorStream
     *            {@code true} to redirect standard error, {@code false}
     *            otherwise.
     * @return this process builder instance.
     */
    public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) {
        this.redirectErrorStream = redirectErrorStream;
        return this;
    }

    /**
     * Starts a new process based on the current state of this process builder.
     *
     * @return the new {@code Process} instance.
     * @throws NullPointerException
     *             if any of the elements of {@link #command()} is {@code null}.
     * @throws IndexOutOfBoundsException
     *             if {@link #command()} is empty.
     * @throws SecurityException
     *             if {@link SecurityManager#checkExec(String)} doesn't allow
     *             process creation.
     * @throws IOException
     *             if an I/O error happens.
     */
    public Process start() throws IOException {
        if (command.isEmpty()) {
            throw new IndexOutOfBoundsException();
        }
        String[] cmdArray = new String[command.size()];
        for (int i = 0; i < cmdArray.length; i++) {
            if ((cmdArray[i] = command.get(i)) == null) {
                throw new NullPointerException();
            }
        }
        String[] envArray = new String[environment.size()];
        int i = 0;
        for (Map.Entry<String, String> entry : environment.entrySet()) {
            envArray[i++] = entry.getKey() + "=" + entry.getValue(); //$NON-NLS-1$
        }
        Process process = Runtime.getRuntime().exec(cmdArray, envArray,
                directory);
        // TODO implement support for redirectErrorStream
        return process;
    }

    private static List<String> toList(String[] strings) {
        ArrayList<String> arrayList = new ArrayList<String>(strings.length);
        for (String string : strings) {
            arrayList.add(string);
        }
        return arrayList;
    }
}
