/**
 * Copyright (c) 2014 Richard Warburton (richard.warburton@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **/
package com.insightfullogic.honest_profiler.testing_utilities;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.function.Consumer;

import static java.lang.Integer.parseInt;

public class AgentRunner {

    private static final Logger logger = LoggerFactory.getLogger(AgentRunner.class);

    public static void run(final String className, final Consumer<AgentRunner> handler) throws IOException {
        AgentRunner runner = new AgentRunner(className);
        runner.start();
        try {
            handler.accept(runner);
        } finally {
            runner.stop();
        }
    }

    private final String className;

    private Process process;
    private int processId;

    private AgentRunner(final String className) {
        this.className = className;
    }

    private void start() throws IOException {
        startProcess();
        readProcessId();
    }

    private void startProcess() throws IOException {
        String java = System.getProperty("java.home") + "/bin/java";
        // Eg: java -agentpath:build/liblagent.so -cp target/classes/ InfiniteExample
        process = new ProcessBuilder()
                .command(java, "-agentpath:build/liblagent.so", "-cp", "target/classes/", className)
                .redirectError(new File("/tmp/error.log"))
                .start();
    }

    private void readProcessId() throws IOException {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line = reader.readLine();
            System.out.println(line);
            processId = parseInt(line);
        }
    }

    private void stop() {
        process.destroy();
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            logger.info(e.getMessage(), e);
        }
    }

    public int getProcessId() {
        return processId;
    }

}

@@ -1678,32 +1678,206 @@
 s IOException %7B%0A
+        run(className, null, handler);%0A    %7D%0A%0A    public static void run(final String className, final String args, final Consumer%3CAgentRunner%3E handler) throws IOException %7B%0A
         AgentRun
@@ -1914,16 +1914,22 @@
 lassName
+, args
 );%0A     
@@ -2096,16 +2096,47 @@
 assName;
+%0A    private final String args;
 %0A%0A    pr
@@ -2232,16 +2232,35 @@
 lassName
+, final String args
 ) %7B%0A    
@@ -2287,24 +2287,50 @@
  className;%0A
+        this.args = args;%0A
     %7D%0A%0A    p
@@ -2548,16 +2548,110 @@
 /java%22;%0A
+        String agentArg = %22-agentpath:build/liblagent.so%22 + (args != null ? %22=%22 + args : %22%22);%0A
         
@@ -2802,39 +2802,16 @@
 va, 
-%22-
 agent
-path:build/liblagent.so%22
+Arg
 , %22-

Allow specifying startup parameters for the agent in tests