/*
 * Copyright (c) 2004-2017, by Alex Leigh.
 * All rights reserved.
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE
 * The copyright notice above does not evidence any
 * actual or intended publication of such source code.
 */

package lc.mecha.exec;

import lc.mecha.log.MechaLogger;
import lc.mecha.log.MechaLoggerFactory;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;

import java.io.*;

/**
 * Executes a PowerShell command on the local Windows system. This mechanism is also capable of executing commands on remote
 * systems via the PowerShell remoting facility (or any other RMI facility installed on the system).
 *
 * @author Alex Leigh
 */
public class LocalPowerShell {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(LocalPowerShell.class);
    private final File script;
    private final File output;
    private final int timeoutMs = 60 * 1000;
    private ByteArrayOutputStream stdout;


    public LocalPowerShell() throws IOException {
        script = File.createTempFile(getClass().getCanonicalName(), ".ps1");
        output = File.createTempFile(getClass().getCanonicalName(), ".output");
    }

    /**
     * Return a new buffered output stream referring to the script associated with this
     * instance. Write to the stream and then close it before calling execute().
     *
     * @return
     * @throws FileNotFoundException
     */
    public OutputStream getScriptStream() throws FileNotFoundException {
        return new BufferedOutputStream(new FileOutputStream(script));
    }

    /**
     * Execute the script represented by this instance. The output of the script will be buffered
     * to a file (on the off chance the result is large enough to overwhelm RAM).
     *
     * @throws IOException
     */
    public void execute() throws IOException {
        final String line = "PowerShell -F " + script.getAbsolutePath();

        stdout = new ByteArrayOutputStream();
        final PumpStreamHandler psh = new PumpStreamHandler(stdout);

        final CommandLine cmdLine = CommandLine.parse(line);
        final DefaultExecutor executor = new DefaultExecutor();
        executor.setStreamHandler(psh);

        final ExecuteWatchdog watchdog = new ExecuteWatchdog(timeoutMs);
        executor.setWatchdog(watchdog);
        executor.execute(cmdLine);

        return;
    }

    public InputStream getStdout() {
        return new ByteArrayInputStream(stdout.toByteArray());
    }

    public String getStdoutString() {
        return stdout.toString();
    }
}
