package nl.hsac.fitnesse.fixture.slim;

import nl.hsac.fitnesse.fixture.util.JsonPathHelper;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;

import java.util.List;

/**
 * Fixture to make Http calls and interpret the result as JSON.
 */
public class JsonHttpTest extends HttpTest {
    private JsonPathHelper pathHelper = getEnvironment().getJsonPathHelper();

    public boolean postValuesAsJsonTo(String serviceUrl) {
        return postToImpl(jsonEncodeCurrentValues(), serviceUrl);
    }
    
    public boolean putValuesAsJsonTo(String serviceUrl) {
        return putToImpl(jsonEncodeCurrentValues(), serviceUrl);
    }

    protected String jsonEncodeCurrentValues() {
        return new JSONObject(getCurrentValues()).toString();
    }

    @Override
    protected String formatValue(String value) {
        return getEnvironment().getHtmlForJson(value);
    }

    public Object jsonPath(String path) {
        String responseString = getResponseBody();
        String jsonPath = getPathExpr(path);
        return pathHelper.getJsonPath(responseString, jsonPath);
    }

    public int jsonPathCount(String path) {
        List<Object> all = getAllMatches(path);
        return all.size();
    }

    protected List<Object> getAllMatches(String path) {
        String responseString = getResponseBody();
        String jsonPath = getPathExpr(path);
        return pathHelper.getAllJsonPath(responseString, jsonPath);
    }

    protected String getResponseBody() {
        String responseString = getResponse().getResponse();
        if (StringUtils.isEmpty(responseString)) {
            throw new SlimFixtureException(false, "No response body available");
        }
        return responseString;
    }

    /**
     * Gets a HTML list with all matches to the supplied JsonPath.
     * @param expr expression to evaluate.
     * @return list containing all results of expression evaluation against last response received, null if there were no matches.
     * @throws RuntimeException if no valid response was available or Json Path could not be evaluated.
     */
    public String allJsonPathMatches(String expr) {
        String result = null;
        List<Object> allJsonPath = getAllMatches(expr);
        if (allJsonPath != null && !allJsonPath.isEmpty()) {
            StringBuilder sb = new StringBuilder();
            sb.append("<div><ul>");
            for (Object match : allJsonPath) {
                sb.append("<li>");
                sb.append(match);
                sb.append("</li>");
            }
            sb.append("</ul></div>");
            result = sb.toString();
        }
        return result;
    }

    /**
     * Update a value in a the response by supplied jsonPath
     * @param path the jsonPath to locate the key whose value needs changing
     * @param value the new value to set
     */
    public void setJsonPathTo(String path, String value) {
        String jsonStr = getResponseBody();
        String jsonPath = getPathExpr(path);
        String newResponse = pathHelper.updateJsonPathWithValue(jsonStr, jsonPath, value);
        getResponse().setResponse(newResponse);
    }

    protected String getPathExpr(String path) {
        String jsonPath = path;
        if (!path.startsWith("$")) {
            if (path.startsWith("[") || path.startsWith(".")) {
                jsonPath = "$" + path;
            } else {
                jsonPath = "$." + path;
            }
        }
        return jsonPath;
    }

    @Override
    protected String urlEncode(String str) {
        String strNoSpaces = str.replace(" ", "+");
        return super.urlEncode(strNoSpaces);
    }
}

@@ -305,87 +305,8 @@
 t %7B%0A
-    private JsonPathHelper pathHelper = getEnvironment().getJsonPathHelper();%0A%0A
     
@@ -352,32 +352,32 @@
 g serviceUrl) %7B%0A
+
         return p
@@ -955,33 +955,36 @@
 %0A        return 
-p
+getP
 athHelper.getJso
@@ -972,24 +972,26 @@
 etPathHelper
+()
 .getJsonPath
@@ -1318,17 +1318,20 @@
  return 
-p
+getP
 athHelpe
@@ -1331,16 +1331,18 @@
 thHelper
+()
 .getAllJ
@@ -2965,17 +2965,20 @@
 ponse = 
-p
+getP
 athHelpe
@@ -2978,16 +2978,18 @@
 thHelper
+()
 .updateJ
@@ -3531,24 +3531,24 @@
 (%22 %22, %22+%22);%0A
-
         retu
@@ -3585,11 +3585,118 @@
 );%0A    %7D
+%0A%0A    protected JsonPathHelper getPathHelper() %7B%0A        return getEnvironment().getJsonPathHelper();%0A    %7D
 %0A%7D%0A

Replace field by access of environment's value on each call