// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.cluster;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLDecoder;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

public class ClusterServiceServletHttpHandler implements HttpRequestHandler {
    private static final Logger s_logger = Logger.getLogger(ClusterServiceServletHttpHandler.class);

    private final ClusterManager manager;

    public ClusterServiceServletHttpHandler(ClusterManager manager) {
        this.manager = manager;
    }

    @Override
    public void handle(HttpRequest request, HttpResponse response, HttpContext context)
    throws HttpException, IOException {

        try {
            if(s_logger.isTraceEnabled()) {
                s_logger.trace("Start Handling cluster HTTP request");
            }

            parseRequest(request);
            handleRequest(request, response);

            if(s_logger.isTraceEnabled()) {
                s_logger.trace("Handle cluster HTTP request done");
            }

        } catch(Throwable e) {
            if(s_logger.isDebugEnabled()) {
                s_logger.debug("Exception " + e.toString());
            }

            try {
            	writeResponse(response, HttpStatus.SC_INTERNAL_SERVER_ERROR, null);
            } catch(Throwable e2) {
                if(s_logger.isDebugEnabled()) {
                    s_logger.debug("Exception " + e2.toString());
                }
            }
        }
    }

    @SuppressWarnings("deprecation")
    private void parseRequest(HttpRequest request) throws IOException {
        if(request instanceof HttpEntityEnclosingRequest) {
            HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest)request;

            String body = EntityUtils.toString(entityRequest.getEntity());
            if(body != null) {
                String[] paramArray = body.split("&");
                if(paramArray != null) {
                    for (String paramEntry : paramArray) {
                        String[] paramValue = paramEntry.split("=");
                        if (paramValue.length != 2) {
                            continue;
                        }

                        String name = URLDecoder.decode(paramValue[0]);
                        String value = URLDecoder.decode(paramValue[1]);

                        if(s_logger.isTraceEnabled()) {
                            s_logger.trace("Parsed request parameter " + name + "=" + value);
                        }
                        request.getParams().setParameter(name, value);
                    }
                }
            }
        }
    }

    private void writeResponse(HttpResponse response, int statusCode, String content) {
        if(content == null) {
            content = "";
        }
        response.setStatusCode(statusCode);
        BasicHttpEntity body = new BasicHttpEntity();
        body.setContentType("text/html; charset=UTF-8");

        byte[] bodyData = content.getBytes();
        body.setContent(new ByteArrayInputStream(bodyData));
        body.setContentLength(bodyData.length);
        response.setEntity(body);
    }

    protected void handleRequest(HttpRequest req, HttpResponse response) {
        String method = (String)req.getParams().getParameter("method");

        int nMethod = RemoteMethodConstants.METHOD_UNKNOWN;
        String responseContent = null;
        try {
            if(method != null) {
                nMethod = Integer.parseInt(method);
            }

            switch(nMethod) {
            case RemoteMethodConstants.METHOD_DELIVER_PDU :
                responseContent = handleDeliverPduMethodCall(req);
                break;

            case RemoteMethodConstants.METHOD_PING :
                responseContent = handlePingMethodCall(req);
                break;

            case RemoteMethodConstants.METHOD_UNKNOWN :
            default :
                assert(false);
                s_logger.error("unrecognized method " + nMethod);
                break;
            }
        } catch(Throwable e) {
            s_logger.error("Unexpected exception when processing cluster service request : ", e);
        }

        if(responseContent != null) {
        	if(s_logger.isTraceEnabled())
        		s_logger.trace("Write reponse with HTTP OK " + responseContent);
        	
            writeResponse(response, HttpStatus.SC_OK, responseContent);
        } else {
        	if(s_logger.isTraceEnabled())
        		s_logger.trace("Write reponse with HTTP Bad request");
        	
            writeResponse(response, HttpStatus.SC_BAD_REQUEST, null);
        }
    }

    private String handleDeliverPduMethodCall(HttpRequest req) {
        
        String pduSeq = (String)req.getParams().getParameter("pduSeq");
        String pduAckSeq = (String)req.getParams().getParameter("pduAckSeq");
        String sourcePeer = (String)req.getParams().getParameter("sourcePeer");
        String destPeer = (String)req.getParams().getParameter("destPeer");
        String agentId = (String)req.getParams().getParameter("agentId");
        String gsonPackage = (String)req.getParams().getParameter("gsonPackage");
        String stopOnError = (String)req.getParams().getParameter("stopOnError");
        String pduType = (String)req.getParams().getParameter("pduType");

        ClusterServicePdu pdu = new ClusterServicePdu();
        pdu.setSourcePeer(sourcePeer);
        pdu.setDestPeer(destPeer);
        pdu.setAgentId(Long.parseLong(agentId));
        pdu.setSequenceId(Long.parseLong(pduSeq));
        pdu.setAckSequenceId(Long.parseLong(pduAckSeq));
        pdu.setJsonPackage(gsonPackage);
        pdu.setStopOnError("1".equals(stopOnError));
        pdu.setPduType(Integer.parseInt(pduType));
        
        manager.OnReceiveClusterServicePdu(pdu);
        return "true";
    }

    private String handlePingMethodCall(HttpRequest req) {
        String callingPeer = (String)req.getParams().getParameter("callingPeer");

        if(s_logger.isDebugEnabled()) {
            s_logger.debug("Handle ping request from " + callingPeer);
        }

        return "true";
    }
}
