package nu.studer.teamcity.buildscan.agent;

import com.intellij.openapi.diagnostic.Logger;
import jetbrains.buildServer.agent.BuildRunnerContext;
import jetbrains.buildServer.agent.ToolCannotBeFoundException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Executes Maven commands and returns their output, both standard output and standard error, when given a {@link BuildRunnerContext}.
 */
final class MavenCommandExecutor {

    private static final Logger LOG = Logger.getInstance("jetbrains.buildServer.BUILDSCAN");

    private final BuildRunnerContext runnerContext;

    MavenCommandExecutor(BuildRunnerContext context) {
        this.runnerContext = context;
    }

    @NotNull
    Result execute(String args) throws IOException, InterruptedException {
        File mavenExec = getMvnExec();
        if (mavenExec == null) {
            return new Result();
        }

        String command = mavenExec.getAbsolutePath() + " " + args;
        ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")).redirectErrorStream(true);
        Process process = processBuilder.start();
        process.waitFor();

        return new Result(process);
    }

    @Nullable
    private File getMvnExec() {
        String mavenPath;
        try {
            mavenPath = runnerContext.getToolPath("maven");
        } catch (ToolCannotBeFoundException e) {
            return null;
        }

        File installationBinDir = new File(mavenPath, "bin");
        String mvnExecutableName = System.getProperty("os.name").toLowerCase().contains("win") ? "mvn.cmd" : "mvn";
        return new File(installationBinDir, mvnExecutableName);
    }

    public static class Result {

        private final Process process;

        public Result() {
            process = null;
        }

        public Result(Process process) {
            this.process = process;
        }

        public boolean isSuccessful() {
            if (process == null) {
                return false;
            }

            return process.exitValue() == 0;
        }

        @NotNull
        public String getOutput() {
            if (process == null || !isSuccessful()) {
                return "";
            }

            StringBuilder sb = new StringBuilder();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            try {
                // this logic eagerly consumes the entire output into memory, which should not be an issue when only
                // used for `mvn --version`, which generates ~5 lines of output
                // this should be revisited if other commands are executed here

                int ch;
                while ((ch = reader.read()) != -1) {
                    sb.append((char) ch);
                }
            } catch (IOException e) {
                LOG.warn("Unable to read output from Maven process", e);
            } finally {
                try {
                    reader.close();
                } catch (IOException e) {
                    LOG.warn("Unable to close reader", e);
                }
            }

            return sb.toString();
        }

    }

}

@@ -1812,23 +1812,16 @@
  %7D%0A%0A    
-public 
 static c
@@ -1834,16 +1834,16 @@
 esult %7B%0A
+
 %0A       
@@ -1879,31 +1879,24 @@
 s;%0A%0A        
-public 
 Result() %7B%0A 
@@ -1941,23 +1941,16 @@
         
-public 
 Result(P
@@ -2022,23 +2022,16 @@
         
-public 
 boolean 
@@ -2212,15 +2212,8 @@
     
-public 
 Stri
@@ -2373,24 +2373,25 @@
 gBuilder();%0A
+%0A
             
@@ -2483,17 +2483,16 @@
 am()));%0A
-%0A
         

Make class and its methods package-scoped