package util;

import com.github.kaeluka.spencer.runtimetransformer.RuntimeTransformer;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class SpencerRunner {
    public static RunResult runWithArgs(final List<String> _args) {
        List<String> args = new ArrayList<String>();
        args.add("../../spencer");
        args.add("--");
        args.addAll(_args);
        ProcessBuilder p = new ProcessBuilder(
                args);
        p.directory(new File("target/test-classes"));
        try {
            final Process process = p.start();

            final InputStreamReader stdoutReader =
                    new InputStreamReader(process.getInputStream());
            final BufferedReader bufferedStdoutReader = new BufferedReader(stdoutReader);
            String line;

            final StringBuilder stdout = new StringBuilder();
            while ((line = bufferedStdoutReader.readLine()) != null) {
                stdout.append("\n");
                stdout.append(line);
            }


            final InputStreamReader stderrReader =
                    new InputStreamReader(process.getErrorStream());
            final BufferedReader bufferedStderrReader = new BufferedReader(stderrReader);

            final StringBuilder stderr = new StringBuilder();
            while ((line = bufferedStderrReader.readLine()) != null) {
                stderr.append("\n");
                stderr.append(line);
            }
            final int exitCode = process.waitFor();
            if (exitCode != 0) {
                throw new RunFailureException(exitCode,
                        stdout.toString(),
                        stderr.toString());
            } else {
                return new RunResult(stdout.toString(), stderr.toString());
            }

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static class RunResult {
        public final String stdout;
        public final String stderr;

        private RunResult(final String stdout, final String stderr) {
            assert stdout != null;
            assert stderr != null;
            this.stdout = stdout;
            this.stderr = stderr;
        }
    }

    public static class RunFailureException extends RuntimeException {

        private final int exitCode;

        public RunFailureException(int exitCode,
                                   final String stdout,
                                   final String stderr) {
            super("program failed with exit code "+exitCode
                    + "\n\n########## stdout:\n"
                    + stdout
                    + "\n\n########## stderr:\n"
                    + stderr);
            assert exitCode != 0;
            this.exitCode = exitCode;
        }
    }
}

@@ -188,32 +188,115 @@
 utStreamReader;%0A
+import java.nio.file.Files;%0Aimport java.nio.file.Path;%0Aimport java.nio.file.Paths;%0A
 import java.util
@@ -424,24 +424,85 @@
 g%3E _args) %7B%0A
+        try %7B%0A%0A            Path testDir = getTestDir();%0A%0A    
         List
@@ -542,32 +542,36 @@
 ing%3E();%0A        
+  
+  
 args.add(%22../../
@@ -577,24 +577,72 @@
 /spencer%22);%0A
+            args.add(%22-tracedir %22+testDir);%0A    
         args
@@ -649,24 +649,28 @@
 .add(%22--%22);%0A
+    
         args
@@ -681,24 +681,28 @@
 All(_args);%0A
+    
         Proc
@@ -748,24 +748,28 @@
             
+    
 args);%0A     
@@ -771,16 +771,20 @@
         
+ 
+   
 p.direct
@@ -821,30 +821,16 @@
 ses%22));%0A
-        try %7B%0A
         
@@ -2050,44 +2050,126 @@
 ult(
-stdout.toString(), stderr.toString()
+%0A                        stdout.toString(),%0A                        stderr.toString(),%0A                        testDir
 );%0A 
@@ -2302,32 +2302,208 @@
 rn null;%0A    %7D%0A%0A
+    private static Path getTestDir() throws IOException %7B%0A        Path ret = Files.createTempDirectory(%22test%22);%0A        ret.toFile().deleteOnExit();%0A        return ret;%0A    %7D%0A%0A
     public stati
@@ -2593,16 +2593,52 @@
  stderr;
+%0A        public final Path tracedir;
 %0A%0A      
@@ -2677,35 +2677,108 @@
  stdout,
- final String stder
+%0A                          final String stderr,%0A                          final Path tracedi
 r) %7B%0A   
@@ -2836,32 +2836,69 @@
 stderr != null;%0A
+            assert tracedir != null;%0A
             this
@@ -2941,32 +2941,279 @@
 tderr = stderr;%0A
+            this.tracedir = tracedir;%0A            assert this.getTracefile().toFile().exists();%0A        %7D%0A%0A        public Path getTracefile() %7B%0A            final Path ret = Paths.get(this.tracedir.toString(), %22tracefile%22);%0A            return ret;%0A
         %7D%0A    %7D%0A

use temporary tracedir for integration tests