package pl.matsuo.gitlab.service.build;


import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import pl.matsuo.gitlab.hook.PartialBuildInfo;
import pl.matsuo.gitlab.hook.PushEvent;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Created by marek on 05.07.15.
 */
public abstract class CommandExecutingPartialBuilder extends PartialBuilder {


  public CompletableFuture<PartialBuildInfo> internalExecute(PushEvent pushEvent, String source, String destination,
                                                             Function<String, String[]> executionCommands,
                                                             Consumer<PartialBuildInfo> afterExecution) {
    PartialBuildInfo partialBuildInfo = new PartialBuildInfo();
    partialBuildInfo.setName(getName());

    CompletableFuture<PartialBuildInfo> future = new CompletableFuture();
    File projectBase = gitRepositoryService.repository(pushEvent);

    File generationBase = new File(projectBase, destination);
    if (!generationBase.mkdirs()) {
      try {
        // FileUtils is better at creating directories than JVM ;)
        FileUtils.forceMkdir(generationBase);
      } catch (IOException e) {
        e.printStackTrace();
        throw new RuntimeException("Cannot create site base directory: " + generationBase.getAbsolutePath());
      }
    }

    // fixme: execute build
    String[] command = executionCommands.apply(generationBase.getAbsolutePath());
    System.out.println("Executing command: " + Arrays.toString(command) + " in directory: " + new File(projectBase, source).getAbsolutePath());
    ProcessBuilder pb = new ProcessBuilder(command);
    pb.environment().put("ci-build", "true");
    pb.directory(new File(projectBase, source));
    try {
      Process process = pb.start();
      process.waitFor();

      String log = IOUtils.toString(process.getInputStream()) + "\n\n"
          + IOUtils.toString(process.getErrorStream());

      partialBuildInfo.setLog(log);
      partialBuildInfo.setExecutionResult(process.exitValue());
      if (process.exitValue() == 0) {
        partialBuildInfo.setStatus("ok");
      }
      System.out.println(log);

      afterExecution.accept(partialBuildInfo);
    } catch (Exception e) {
      ByteArrayOutputStream os = new ByteArrayOutputStream();
      e.printStackTrace(new PrintWriter(os));
      partialBuildInfo.setLog(new String(os.toByteArray()));
      e.printStackTrace();
    }

    future.complete(partialBuildInfo);

    return future;
  }
}


@@ -201,16 +201,47 @@
 Event;%0A%0A
+import java.io.BufferedReader;%0A
 import j
@@ -270,16 +270,16 @@
 Stream;%0A
-
 import j
@@ -319,16 +319,50 @@
 eption;%0A
+import java.io.InputStreamReader;%0A
 import j
@@ -406,16 +406,16 @@
 Arrays;%0A
-
 import j
@@ -453,16 +453,54 @@
 Future;%0A
+import java.util.concurrent.TimeUnit;%0A
 import j
@@ -2124,160 +2124,675 @@
 ();%0A
+%0A
       
-process.waitFor();%0A%0A      String log = IOUtils.toString(process.getInputStream()) + %22%5Cn%5Cn%22%0A
+BufferedReader out = new BufferedReader(new InputStreamReader(process.getInputStream()));%0A      BufferedReader err = new BufferedReader(new InputStreamReader(process.getInputStream()));%0A      String log = %22%22;%0A%0A      while (process.isAlive()) %7B%0A        System.out.println(%22...%22);%0A        process.waitFor(3, TimeUnit.SECONDS);%0A%0A        while (out.ready()) %7B%0A          String line = out.readLine();%0A          System.out.println(%22    :: %22 + line);%0A          log = log + %22%5Cn%22 + line;%0A  
      
+ %7D%0A%0A
      
-+ IOUtils.toString(process.getErrorStream());
+   while (err.ready()) %7B%0A          String line = err.readLine();%0A          System.out.println(%22    !! %22 + line);%0A          log = log + %22%5Cn%22 + line;%0A        %7D%0A      %7D
 %0A%0A  
@@ -2980,39 +2980,8 @@
    %7D
-%0A      System.out.println(log);
 %0A%0A  

Write out/err from commands to log in 3 second intervals