package org.shipkit.internal.gradle.exec;

import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.StopExecutionException;
import org.gradle.process.ExecResult;
import org.gradle.process.ExecSpec;
import org.shipkit.gradle.exec.ExecCommand;

import java.io.File;
import java.util.List;

import static java.util.Arrays.asList;

public class ExecCommandFactory {

    private final static Logger LOG = Logging.getLogger(ExecCommandFactory.class);

    public static Action<ExecSpec> ignoreResult() {
        return new Action<ExecSpec>() {
            public void execute(ExecSpec spec) {
                spec.setIgnoreExitValue(true);
            }
        };
    }

    public static Action<ExecSpec> ignoreResult(final File workingDir) {
        return new Action<ExecSpec>() {
            public void execute(ExecSpec spec) {
                spec.setIgnoreExitValue(true);
                spec.setWorkingDir(workingDir);
            }
        };
    }

    public static Action<ExecResult> stopExecution() {
        return new Action<ExecResult>() {
            public void execute(ExecResult exec) {
                if (exec.getExitValue() != 0) {
                    LOG.info("External process returned exit code: {}. Stopping the execution of the task.", exec.getExitValue());
                    //Cleanly stop executing the task, without making the task failed.
                    throw new StopExecutionException();
                }
            }
        };
    }

    private static Action<ExecResult> ensureSucceeded(final String prefix) {
        return new Action<ExecResult>() {
            public void execute(ExecResult result) {
                ensureSucceeded(result, prefix);
            }
        };
    }

    static void ensureSucceeded(ExecResult result, String prefix) {
        if (result.getExitValue() != 0) {
            throw new GradleException("External process failed with exit code " + result.getExitValue() + "\n" +
                    "Please inspect the command output prefixed with '" + prefix.trim() + "' the build log.");
        }
    }

    /**
     * Exec command that will throw the exception when the command line fails.
     * This is the most typical kind of exec command.
     */
    public static ExecCommand execCommand(String description, List<String> commandLine) {
        String prefix = defaultPrefix(commandLine);
        return new ExecCommand(prefix, description, commandLine, ignoreResult(), ensureSucceeded(prefix));
    }

    /**
     * See {@link #execCommand(String, List)}
     */
    public static ExecCommand execCommand(String description, String... commandLine) {
        return execCommand(description, asList(commandLine));
    }

    /**
     * See {@link #execCommand(String, List)}
     */
    public static ExecCommand execCommand(String description, File workingDir, String... commandLine) {
        List<String> cmd = asList(commandLine);
        String prefix = defaultPrefix(cmd);
        return new ExecCommand(prefix, description, cmd, ignoreResult(workingDir), ensureSucceeded(prefix));
    }

    static String defaultPrefix(List<String> commandLine) {
        String prefix = commandLine.size() > 1 ? commandLine.get(1) : commandLine.get(0);
        return "[" + prefix + "] ";
    }

    /**
     * Exec command with custom result action.
     * Useful if the user needs custom behavior when command line finishes executing.
     * For example, we can ignore the failure.
     */
    public static ExecCommand execCommand(String description, List<String> commandLine, Action<ExecResult> resultAction) {
        return new ExecCommand(defaultPrefix(commandLine), description, commandLine, ignoreResult(), resultAction);
    }
}

@@ -628,97 +628,15 @@
 urn 
-new Action%3CExecSpec%3E() %7B%0A            public void execute(ExecSpec spec) %7B%0A               
+spec -%3E
  spe
@@ -667,33 +667,8 @@
 e);%0A
-            %7D%0A        %7D;%0A
     
@@ -762,86 +762,18 @@
 urn 
-new Action%3CExecSpec%3E() %7B%0A            public void execute(ExecSpec spec) %7B%0A    
+spec -%3E %7B%0A
     
@@ -815,36 +815,32 @@
 e);%0A            
- 
-   
 spec.setWorkingD
@@ -855,30 +855,16 @@
 ngDir);%0A
-            %7D%0A
         
@@ -947,90 +947,18 @@
 urn 
-new Action%3CExecResult%3E() %7B%0A            public void execute(ExecResult exec) %7B%0A    
+exec -%3E %7B%0A
     
@@ -1013,20 +1013,16 @@
         
-    
 LOG.info
@@ -1140,20 +1140,16 @@
         
-   
- 
 //Cleanl
@@ -1215,36 +1215,32 @@
                 
-    
 throw new StopEx
@@ -1263,26 +1263,8 @@
 ();%0A
-                %7D%0A
     
@@ -1387,103 +1387,17 @@
 urn 
-new Action%3CExecResult%3E() %7B%0A            public void execute(ExecResult result) %7B%0A               
+result -%3E
  ens
@@ -1430,33 +1430,8 @@
 x);%0A
-            %7D%0A        %7D;%0A
     

replace with lambda