package org.couchbase.mock.http.capi;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.http.*;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.util.EntityUtils;
import org.couchbase.mock.Bucket;
import org.couchbase.mock.JsonUtils;
import org.couchbase.mock.httpio.HandlerUtil;
import org.couchbase.mock.memcached.Item;
import org.couchbase.mock.memcached.Storage;
import org.couchbase.mock.views.Configuration;
import org.couchbase.mock.views.QueryExecutionException;
import org.couchbase.mock.views.View;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public class ViewHandler implements HttpRequestHandler {
    final View view;
    final Bucket bucket;

    public ViewHandler(View view, Bucket bucket) {
        this.view = view;
        this.bucket = bucket;
    }

    @Override
    public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
        // For now, ignore the configuration
        Iterable<Item> items = bucket.getMasterItems(Storage.StorageType.CACHE);
        String queryString = null;
        Configuration viewParams = null;

        if (request.getRequestLine().getMethod().equals("GET")) {
            URL url = HandlerUtil.getUrl(request);
            queryString = url.getQuery();

        } else if (request.getRequestLine().getMethod().equals("POST")) {
            // Request bodies sent to POST are raw JSON, not URL-encoded

            HttpEntity reqEntity = ((HttpEntityEnclosingRequest)request).getEntity();
            String contentType = reqEntity.getContentType().getValue();
            String rawPayload = EntityUtils.toString(reqEntity);

            if (contentType.equals(ContentType.APPLICATION_JSON.getMimeType())) {
                JsonObject jsonDecoded = JsonUtils.decode(rawPayload, JsonObject.class);
                Map<String,String> confParams = new HashMap<String, String>();

                for (Map.Entry<String,JsonElement> entry : jsonDecoded.entrySet()) {
                    confParams.put(entry.getKey(), entry.getValue().toString());
                }
                viewParams = new Configuration(confParams);

            } else if (contentType.equals(ContentType.APPLICATION_FORM_URLENCODED.getMimeType())) {
                queryString = rawPayload;
            }
        }

        if (queryString != null && !queryString.isEmpty()) {
            try {
                Map<String,String> kvParams = HandlerUtil.getQueryParams(queryString);
                viewParams = new Configuration(kvParams);
            } catch (MalformedURLException ex) {
                String errMessage = ex.getMessage();
                if (errMessage == null) {
                    errMessage = "Internal Error for " + queryString;
                }
                HandlerUtil.makeJsonResponse(response, errMessage);
                response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
                return;
            }
        } else if (viewParams == null) {
            viewParams = new Configuration();
        }

        try {
            String s = view.executeRaw(items, viewParams);
            HandlerUtil.makeJsonResponse(response, s);
            response.setStatusCode(HttpStatus.SC_OK);
            StringEntity entity = (StringEntity)response.getEntity();
            entity.setChunked(true);

        } catch (QueryExecutionException ex) {
            HandlerUtil.makeJsonResponse(response, ex.getJsonString());
            response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
        }
    }
}

@@ -1198,53 +1198,8 @@
 n %7B%0A
-        // For now, ignore the configuration%0A
     
@@ -1287,232 +1287,113 @@
     
-String queryString = null;%0A        Configuration viewParams = null;%0A%0A        if (request.getRequestLine().getMethod().equals(%22GET%22)) %7B%0A            URL url = HandlerUtil.getUrl(request);%0A            queryString = url.getQuery
+URL url = HandlerUtil.getUrl(request);%0A        Map%3CString,String%3E paramsMap = new HashMap%3CString, String%3E
 ();%0A
@@ -1397,31 +1397,24 @@
 );%0A%0A        
-%7D else 
 if (request.
@@ -1464,82 +1464,8 @@
 ) %7B%0A
-            // Request bodies sent to POST are raw JSON, not URL-encoded%0A%0A
     
@@ -1696,24 +1696,25 @@
         if (
+!
 contentType.
@@ -1763,32 +1763,231 @@
 eType())) %7B%0A    
+            HandlerUtil.makeJsonResponse(response, %22Content type must be application/json%22);%0A                response.setStatusCode(HttpStatus.SC_BAD_REQUEST);%0A                return;%0A            %7D%0A%0A
             Json
@@ -2059,92 +2059,8 @@
 s);%0A
-                Map%3CString,String%3E confParams = new HashMap%3CString, String%3E();%0A%0A    
     
@@ -2156,22 +2156,17 @@
     
-    confP
+p
 arams
+Map
 .put
@@ -2216,36 +2216,32 @@
 ));%0A            
-    
 %7D%0A              
@@ -2230,32 +2230,35 @@
   %7D%0A        
+%7D%0A%0A
         
 viewParams =
@@ -2249,219 +2249,44 @@
     
-viewParams = new Configuration(confParams);%0A%0A            %7D else if (contentType.equals(ContentType.APPLICATION_FORM_URLENCODED.getMimeType())) %7B%0A                queryString = rawPayload;%0A            %7D%0A        %7D%0A
+String queryString = url.getQuery();
 %0A   
@@ -2380,32 +2380,33 @@
      Map%3CString,
+ 
 String%3E kvParams
@@ -2469,38 +2469,24 @@
     
-viewParams = new Configuration
+paramsMap.putAll
 (kvP
@@ -2911,95 +2911,8 @@
    %7D
- else if (viewParams == null) %7B%0A            viewParams = new Configuration();%0A        %7D
 %0A%0A  
@@ -2973,18 +2973,36 @@
 ms, 
-viewP
+new Configuration(p
 arams
+Map)
 );%0A 

Merge GET and POST params