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;

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 REMOTE_ADDR = "REMOTE_ADDR";
    private static final String SERVER_NAME = "SERVER_NAME";
    private static final String SERVER_PORT = "SERVER_PORT";
    private static final String SERVER_PROTOCOL = "SERVER_PROTOCOL";

    @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(REMOTE_ADDR, request.getRemoteAddr());
        generator.writeStringField(SERVER_NAME, request.getServerName());
        generator.writeNumberField(SERVER_PORT, request.getServerPort());
        generator.writeStringField(SERVER_PROTOCOL, request.getProtocol());
        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 {
        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();
    }
}

@@ -789,16 +789,20 @@
  String 
+ENV_
 REMOTE_A
@@ -850,24 +850,28 @@
 inal String 
+ENV_
 SERVER_NAME 
@@ -911,32 +911,36 @@
 ic final String 
+ENV_
 SERVER_PORT = %22S
@@ -988,42 +988,501 @@
 ing 
-SERVER_PROTOCOL = %22SERVER_PROTOCOL
+ENV_LOCAL_ADDR = %22LOCAL_ADDR%22;%0A    private static final String ENV_LOCAL_NAME = %22LOCAL_NAME%22;%0A    private static final String ENV_LOCAL_PORT = %22LOCAL_PORT%22;%0A    private static final String ENV_SERVER_PROTOCOL = %22SERVER_PROTOCOL%22;%0A    private static final String ENV_REQUEST_SECURE = %22REQUEST_SECURE%22;%0A    private static final String ENV_REQUEST_ASYNC = %22REQUEST_ASYNC%22;%0A    private static final String ENV_AUTH_TYPE = %22AUTH_TYPE%22;%0A    private static final String ENV_REMOTE_USER = %22REMOTE_USER
 %22;%0A%0A
@@ -2520,16 +2520,20 @@
 ngField(
+ENV_
 REMOTE_A
@@ -2594,24 +2594,28 @@
 StringField(
+ENV_
 SERVER_NAME,
@@ -2672,24 +2672,28 @@
 NumberField(
+ENV_
 SERVER_PORT,
@@ -2758,44 +2758,671 @@
 eld(
-SERVER_PROTOCOL, request.getProtocol
+ENV_LOCAL_ADDR, request.getLocalAddr());%0A        generator.writeStringField(ENV_LOCAL_NAME, request.getLocalName());%0A        generator.writeNumberField(ENV_LOCAL_PORT, request.getLocalPort());%0A        generator.writeStringField(ENV_SERVER_PROTOCOL, request.getProtocol());%0A        generator.writeBooleanField(ENV_REQUEST_SECURE, request.isSecure());%0A        generator.writeBooleanField(ENV_REQUEST_ASYNC, request.isAsyncStarted());%0A        generator.writeStringField(ENV_AUTH_TYPE, request.getAuthType());%0A        //TODO: Should that be really displayed here ? Consider the user interface?%0A        generator.writeStringField(ENV_REMOTE_USER, request.getRemoteUser
 ());

Add more details to the HTTP environment