package net.kencochrane.raven.marshaller.json;

import com.fasterxml.jackson.core.JsonGenerator;
import net.kencochrane.raven.event.interfaces.HttpInterface;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;

/**
 * Binding system allowing to convert an {@link HttpInterface} into a JSON stream.
 */
public class HttpInterfaceBinding implements InterfaceBinding<HttpInterface> {
    private static final String URL = "url";
    private static final String METHOD = "method";
    private static final String DATA = "data";
    private static final String QUERY_STRING = "query_string";
    private static final String COOKIES = "cookies";
    private static final String HEADERS = "headers";
    private static final String ENVIRONMENT = "env";
    private static final String ENV_REMOTE_ADDR = "REMOTE_ADDR";
    private static final String ENV_SERVER_NAME = "SERVER_NAME";
    private static final String ENV_SERVER_PORT = "SERVER_PORT";
    private static final String ENV_LOCAL_ADDR = "LOCAL_ADDR";
    private static final String ENV_LOCAL_NAME = "LOCAL_NAME";
    private static final String ENV_LOCAL_PORT = "LOCAL_PORT";
    private static final String ENV_SERVER_PROTOCOL = "SERVER_PROTOCOL";
    private static final String ENV_REQUEST_SECURE = "REQUEST_SECURE";
    private static final String ENV_REQUEST_ASYNC = "REQUEST_ASYNC";
    private static final String ENV_AUTH_TYPE = "AUTH_TYPE";
    private static final String ENV_REMOTE_USER = "REMOTE_USER";

    @Override
    public void writeInterface(JsonGenerator generator, HttpInterface httpInterface) throws IOException {
        HttpServletRequest request = httpInterface.getRequest();

        generator.writeStartObject();
        generator.writeStringField(URL, request.getRequestURL().toString());
        generator.writeStringField(METHOD, request.getMethod());
        generator.writeFieldName(DATA);
        writeData(generator, request.getParameterMap());
        generator.writeStringField(QUERY_STRING, request.getQueryString());
        generator.writeFieldName(COOKIES);
        writeCookies(generator, request.getCookies());
        generator.writeFieldName(HEADERS);
        writeHeaders(generator, request);
        generator.writeFieldName(ENVIRONMENT);
        writeEnvironment(generator, request);
        generator.writeEndObject();
    }

    private void writeEnvironment(JsonGenerator generator, HttpServletRequest request) throws IOException {
        generator.writeStartObject();
        generator.writeStringField(ENV_REMOTE_ADDR, request.getRemoteAddr());
        generator.writeStringField(ENV_SERVER_NAME, request.getServerName());
        generator.writeNumberField(ENV_SERVER_PORT, request.getServerPort());
        generator.writeStringField(ENV_LOCAL_ADDR, request.getLocalAddr());
        generator.writeStringField(ENV_LOCAL_NAME, request.getLocalName());
        generator.writeNumberField(ENV_LOCAL_PORT, request.getLocalPort());
        generator.writeStringField(ENV_SERVER_PROTOCOL, request.getProtocol());
        generator.writeBooleanField(ENV_REQUEST_SECURE, request.isSecure());
        generator.writeBooleanField(ENV_REQUEST_ASYNC, request.isAsyncStarted());
        generator.writeStringField(ENV_AUTH_TYPE, request.getAuthType());
        //TODO: Should that be really displayed here ? Consider the user interface?
        generator.writeStringField(ENV_REMOTE_USER, request.getRemoteUser());
        generator.writeEndObject();
    }

    private void writeHeaders(JsonGenerator generator, HttpServletRequest request) throws IOException {
        generator.writeStartObject();
        for (String header : Collections.list(request.getHeaderNames())) {
            generator.writeArrayFieldStart(header);
            for (String headerValue : Collections.list(request.getHeaders(header))) {
                generator.writeString(headerValue);
            }
            generator.writeEndArray();
        }
        generator.writeEndObject();
    }

    private void writeCookies(JsonGenerator generator, Cookie[] cookies) throws IOException {
        //TODO: Cookies shouldn't be sent by default
        if (cookies == null) {
            generator.writeNull();
            return;
        }

        generator.writeStartObject();
        for (Cookie cookie : cookies) {
            generator.writeStringField(cookie.getName(), cookie.getValue());
        }
        generator.writeEndObject();
    }

    private void writeData(JsonGenerator generator, Map<String, String[]> parameterMap) throws IOException {
        if (parameterMap == null) {
            generator.writeNull();
            return;
        }

        generator.writeStartObject();
        for (Map.Entry<String, String[]> parameter : parameterMap.entrySet()) {
            generator.writeArrayFieldStart(parameter.getKey());
            for (String parameterValue : parameter.getValue()) {
                generator.writeString(parameterValue);
            }
            generator.writeEndArray();
        }
        generator.writeEndObject();
    }
}

@@ -287,17 +287,73 @@
 llection
-s
+;%0Aimport java.util.Collections;%0Aimport java.util.Iterator
 ;%0Aimport
@@ -3856,31 +3856,25 @@
 or.write
-ArrayFieldStart
+FieldName
 (header)
@@ -3883,35 +3883,94 @@
             
-for (
+StringBuilder sb = new StringBuilder();%0A            Collection%3C
 String
+%3E
  headerValue
@@ -3969,18 +3969,19 @@
 derValue
- :
+s =
  Collect
@@ -4017,19 +4017,17 @@
 header))
-)
- %7B
+;
 %0A       
@@ -4035,47 +4035,231 @@
     
-    generator.writeString(headerValue);
+for (Iterator%3CString%3E it = headerValues.iterator(); it.hasNext(); ) %7B%0A                sb.append(%22' %22).append(it.next()).append(%22 '%22);%0A                if (it.hasNext()) %7B%0A                    sb.append(%22,%22);%0A                %7D
 %0A   
@@ -4292,33 +4292,44 @@
 erator.write
-EndArray(
+String(sb.toString()
 );%0A        %7D

Send HTTP Header values as a single String instead of a List