// Copyright (c) 2015 Uber Technologies, Inc.
//
// 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.uber.jenkins.phabricator.conduit;

import com.uber.jenkins.phabricator.CommonUtils;
import hudson.Launcher;
import net.sf.json.JSONObject;
import net.sf.json.groovy.JsonSlurper;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class ArcanistClient {
    private final String methodName;
    private final Map<String, String> params;
    private final String conduitToken;

    public ArcanistClient(String methodName, Map<String, String> params, String conduitToken) {
        this.methodName = methodName;
        this.params = params;
        this.conduitToken = conduitToken;
    }

    public JSONObject callConduit(Launcher.ProcStarter starter, PrintStream stderr) throws IOException, InterruptedException {
        JSONObject obj = new JSONObject();
        obj.putAll(this.params);
        List<String> command = new ArrayList<String>(Arrays.asList("sh", "-c", "echo '" + obj.toString() + "' | arc call-conduit " + this.methodName));
        if (!CommonUtils.isBlank(this.conduitToken)) {
            command.add(" --conduit-token=" + this.conduitToken);
        }
        ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();

        // TODO handle bad return code
        starter.cmds(command).stdout(stdoutBuffer).stderr(stderr).join();
        JsonSlurper jsonParser = new JsonSlurper();
        try {
            return (JSONObject) jsonParser.parseText(stdoutBuffer.toString());
        } catch(net.sf.json.JSONException e) {
            stderr.println("[phabricator] Unable to parse JSON from response: " + stdoutBuffer.toString());
            throw e;
        }
    }
}

@@ -1865,16 +1865,360 @@
 %0A    %7D%0A%0A
+    private String getConduitCommand(String methodName) %7B%0A        StringBuilder sb = new StringBuilder(%22arc call-conduit %22);%0A        sb.append(methodName);%0A        if (!CommonUtils.isBlank(this.conduitToken)) %7B%0A            sb.append(%22 --conduit-token=%22);%0A            sb.append(this.conduitToken);%0A        %7D%0A        return sb.toString();%0A    %7D%0A%0A
     publ
@@ -2465,16 +2465,33 @@
 String%3E(
+%0A                
 Arrays.a
@@ -2544,25 +2544,8 @@
 %22' %7C
- arc call-conduit
  %22 +
@@ -2554,152 +2554,45 @@
 his.
-methodName));%0A        if (!CommonUtils.isBlank
+getConduitCommand
 (this.
-conduitToken)) %7B%0A            command.add(%22 --conduit-token=%22 + this.conduitToken);%0A        %7D
+methodName)));
 %0A   

Fix string escaping