// Copyright © 2010, Esko Luontola <www.orfjackal.net>
// This software is released under the Apache License 2.0.
// The license text is at http://www.apache.org/licenses/LICENSE-2.0

package net.orfjackal.sbt.runner;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;

import java.io.*;
import java.util.*;

public class SbtRunner {

    private static final String PROMPT = "\n> ";
    private static final String FAILED_TO_COMPILE_PROMPT = "Hit enter to retry or 'exit' to quit:";
    private static final String PROMPT_AFTER_EMPTY_ACTION = "> ";
    private static final String ERROR_RUNNING_ACTION_PREFIX = "[error] Error running ";
    private static final Logger LOG = Logger.getInstance("#orfjackal.sbt.runner.SbtRunner");

    private final ProcessRunner sbt;

    public SbtRunner(File workingDir, File launcherJar, String[] vmParameters) {
        if (!workingDir.isDirectory()) {
            throw new IllegalArgumentException("Working directory does not exist: " + workingDir);
        }
        if (!launcherJar.isFile()) {
            throw new IllegalArgumentException("Launcher JAR file does not exist: " + launcherJar);
        }
        sbt = new ProcessRunner(workingDir, getCommand(launcherJar, vmParameters));
    }

    private static String[] getCommand(File launcherJar, String[] vmParameters) {
        List<String> command = new ArrayList<String>();

        command.add("java");
        command.addAll(Arrays.asList(vmParameters));
        command.addAll(Arrays.asList(
                "-Dsbt.log.noformat=true",
                "-Djline.terminal=jline.UnsupportedTerminal",
                "-jar",
                launcherJar.getAbsolutePath()
        ));

        LOG.info("SBT command line: " + StringUtil.join(command, " "));
        return command.toArray(new String[command.size()]);
    }

    public OutputReader subscribeToOutput() {
        return sbt.subscribeToOutput();
    }

    public void start() throws IOException {
        // TODO: detect if the directory does not have a project
        OutputReader output = sbt.subscribeToOutput();
        sbt.start();
        sbt.destroyOnShutdown();
        output.waitForOutput(Arrays.asList(PROMPT, FAILED_TO_COMPILE_PROMPT));
        output.close();
    }

    public void destroy() {
        sbt.destroy();
    }

    public boolean isAlive() {
        return sbt.isAlive();
    }

    /**
     * @param action  the SBT action to run, e.g. "compile"
     * @return        false if an error was parsed from the output, true otherwise
     * @throws java.io.IOException
     */
    public boolean execute(String action) throws IOException {
        OutputReader output = sbt.subscribeToOutput();
        try {
            sbt.writeInput(action + "\n");

        if (action.trim().equals("")) {
            output.waitForOutput(Arrays.asList(PROMPT_AFTER_EMPTY_ACTION, FAILED_TO_COMPILE_PROMPT));
        } else {
            output.waitForOutput(Arrays.asList(PROMPT, FAILED_TO_COMPILE_PROMPT));
        }
            boolean error = output.endOfOutputContains(ERROR_RUNNING_ACTION_PREFIX);
            return !error;
        } finally {
            output.close();
        }
    }
}

@@ -2442,17 +2442,16 @@
  action 
- 
 the SBT 
@@ -2495,23 +2495,16 @@
 @return 
-       
 false if
@@ -2779,24 +2779,28 @@
 );%0A%0A        
+    
 if (action.t
@@ -2815,24 +2815,28 @@
 uals(%22%22)) %7B%0A
+    
             
@@ -2933,16 +2933,20 @@
         
+ 
+   
 %7D else %7B
@@ -2946,16 +2946,20 @@
  else %7B%0A
+    
         
@@ -3037,30 +3037,88 @@
 ));%0A        
+ 
+   
 %7D%0A    
+    %7D finally %7B%0A            output.close();%0A        %7D%0A
         bool
@@ -3190,28 +3190,24 @@
 X);%0A        
-    
 return !erro
@@ -3213,66 +3213,8 @@
 or;%0A
-        %7D finally %7B%0A            output.close();%0A        %7D%0A
     

fix formatting