package com.urbancode.air.plugin.linux

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

import com.urbancode.commons.util.concurrent.WaitFuture;
import com.urbancode.commons.util.processes.Processes;
import com.urbancode.air.ExitCodeException;

public class RebootHelper {
    private volatile boolean isShuttingDown = false;

    private final def pb;
    private final def time;

    private def out = System.out;

    public RebootHelper(time) {
        pb = new ProcessBuilder().directory(new File('.'));
        if (time != null && time.trim() != "" ) {
            this.time = time;
        }
        else {
            this.time = "now";
        }
    }

    public void run() {
        String[] command = ['shutdown', '-r', this.time];
        pb.command(command);

        println();
        println(command.join(' '));

        Thread hook = null;
        Process proc = pb.start();
        try {
            hook = {
                this.isShuttingDown = true;
                proc.destroy();
            } as Thread;

            try {
                Runtime.getRuntime().addShutdownHook(hook);
            }
            catch (IllegalStateException e) {
                // Swallow. Nothing we can do about the JVM shutting down
            }
            proc.out.close(); // close stdin
            def out = new PrintStream(this.out, true);
            try {
                def procUtils = new Processes();
                def outputFuture = procUtils.redirectOutput(proc, out);
                def errorFuture = procUtils.redirectError(proc, out);

                outputFuture.get();
                errorFuture.get();
                proc.waitFor();

                proc.getInputStream().close();
                proc.getErrorStream().close();
                // not closing out here because AutomationPluginRunnable does that.
            }
            catch(Exception e) {
                if (!this.isShuttingDown) {
                    throw e;
                }
            }
            finally {
                out.flush();
            }
        }
        finally {
            proc.destroy();
            if (hook != null) {
                try {
                    Runtime.getRuntime().removeShutdownHook(hook);
                }
                catch (IllegalStateException e) {
                    // Swallow. Nothing we can do about the JVM shutting down
                }
            }
        }
        int exitValue = proc.exitValue();
        if (exitValue) {
            // When the shutdown -r command runs, it sends SIGTERM to all processes
            // 143 is a legitimate case
            if (exitValue != 143) {
                throw new ExitCodeException(exitValue);
            }
        }
    }
}
