package org.implab.gradle.common.exec;

import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;

class SystemExec implements Executor {

    private final ProcessBuilder builder = new ProcessBuilder();

    private RedirectFrom inputRedirect;

    private RedirectTo outputRedirect;

    private RedirectTo errorRedirect;

    @Override
    public CompletableFuture<Integer> start() throws IOException {
        // TODO Auto-generated method stub
        var tasks = new ArrayList<CompletableFuture<?>>();

        // discard stdout if not redirected
        if (outputRedirect == null)
            builder.redirectOutput(Redirect.DISCARD);

        // discard stderr if not redirected
        if (errorRedirect == null)
            builder.redirectError(Redirect.DISCARD);

        // run process
        var proc = builder.start();

        tasks.add(proc.onExit());

        if (inputRedirect != null)
            tasks.add(inputRedirect.redirect(proc.getOutputStream()));

        if (outputRedirect != null)
            tasks.add(outputRedirect.redirect(proc.getInputStream()));

        if (errorRedirect != null)
            tasks.add(errorRedirect.redirect(proc.getErrorStream()));

        return CompletableFuture
                .allOf(tasks.toArray(new CompletableFuture<?>[0]))
                .thenApply(t -> proc.exitValue());
    }

    public void command(String... args) {
        builder.command(args);
    }

    public void directory(File workingDir) {
        builder.directory(workingDir);
    }

    public void stderr(RedirectTo to) {
        errorRedirect = to;
    }

    public void stdin(RedirectFrom from) {
        inputRedirect = from;
    }

    public void stdout(RedirectTo to) {
        outputRedirect = to;
    }

    @Override
    public void argument(String arg) {
        builder.command().add(arg);
    }

}
