/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * 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.
 */
package flex.messaging.services.http.proxy;

import flex.messaging.FlexContext;
import flex.messaging.FlexSession;
import flex.messaging.io.MessageIOConstants;
import flex.messaging.log.Log;
import flex.messaging.log.Logger;
import flex.messaging.services.HTTPProxyService;
import flex.messaging.services.http.ExternalProxySettings;
import flex.messaging.services.http.httpclient.FlexGetMethod;
import flex.messaging.services.http.httpclient.FlexPostMethod;
import flex.messaging.util.StringUtils;
import flex.messaging.util.URLEncoder;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.OptionsMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.methods.TraceMethod;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 *
 * Sends the request to the endpoint, including custom copying of headers and cookies.
 */
public class RequestFilter extends ProxyFilter
{
    private static final int CAUGHT_ERROR = 10706;
    private static final int UNKNOWN_HOST = 10707;
    private static final int INVALID_METHOD = 10719;
    private static final String STRING_JSESSIONID = "jsessionid";

    /**
     * Invoke the filter.
     *
     * @param context the context
     */
    public void invoke(ProxyContext context)
    {
        setupRequest(context);
        copyCookiesToEndpoint(context);
        copyHeadersToEndpoint(context);
        addCustomHeaders(context);
        recordRequestHeaders(context);
        sendRequest(context);

        if (next != null)
        {
            next.invoke(context);
        }
    }

    /**
     * Setup the request.
     *
     * @param context the context
     */
    protected void setupRequest(ProxyContext context)
    {
        // set the proxy to send requests through
        ExternalProxySettings externalProxy = context.getExternalProxySettings();
        if (externalProxy != null)
        {
            String proxyServer = externalProxy.getProxyServer();

            if (proxyServer != null)
            {
                context.getTarget().getHostConfig().setProxy(proxyServer, externalProxy.getProxyPort());
                if (context.getProxyCredentials() != null)
                {
                    context.getHttpClient().getState().setProxyCredentials(ProxyUtil.getDefaultAuthScope(), context.getProxyCredentials());
                }
            }
        }

        String method = context.getMethod();
        String encodedPath = context.getTarget().getEncodedPath();
        if (MessageIOConstants.METHOD_POST.equals(method))
        {
            FlexPostMethod postMethod = new FlexPostMethod(encodedPath);
            context.setHttpMethod(postMethod);
            if (context.hasAuthorization())
            {
                postMethod.setConnectionForced(true);
            }
        }
        else if (ProxyConstants.METHOD_GET.equals(method))
        {
            FlexGetMethod getMethod = new FlexGetMethod(context.getTarget().getEncodedPath());
            context.setHttpMethod(getMethod);
            if (context.hasAuthorization())
            {
                getMethod.setConnectionForced(true);
            }
        }
        else if (ProxyConstants.METHOD_HEAD.equals(method))
        {
            HeadMethod headMethod = new HeadMethod(encodedPath);
            context.setHttpMethod(headMethod);
        }
        else if (ProxyConstants.METHOD_PUT.equals(method))
        {
            PutMethod putMethod = new PutMethod(encodedPath);
            context.setHttpMethod(putMethod);
        }
        else if (ProxyConstants.METHOD_OPTIONS.equals(method))
        {
            OptionsMethod optionsMethod = new OptionsMethod(encodedPath);
            context.setHttpMethod(optionsMethod);
        }
        else if (ProxyConstants.METHOD_DELETE.equals(method))
        {
            DeleteMethod deleteMethod = new DeleteMethod(encodedPath);
            context.setHttpMethod(deleteMethod);
        }
        else if (ProxyConstants.METHOD_TRACE.equals(method))
        {
            TraceMethod traceMethod = new TraceMethod(encodedPath);
            context.setHttpMethod(traceMethod);
        }
        else
        {
            ProxyException pe = new ProxyException(INVALID_METHOD);
            pe.setDetails(INVALID_METHOD, "1", new Object[] { method });
            throw pe;
        }

        HttpMethodBase httpMethod = context.getHttpMethod();
        if (httpMethod instanceof EntityEnclosingMethod)
        {
            ((EntityEnclosingMethod)httpMethod).setContentChunked(context.getContentChunked());
        }
    }

    /**
     * Before calling the endpoint, set up the cookies found in the request.
     * @param context the context
     */
    public static void copyCookiesToEndpoint(ProxyContext context)
    {
        HttpServletRequest clientRequest = FlexContext.getHttpRequest();
        context.clearRequestCookies();
        if (clientRequest != null)
        {
            javax.servlet.http.Cookie[] cookies = clientRequest.getCookies();
            HttpState initState = context.getHttpClient().getState();

            if (cookies != null)
            {
                // Gather up the cookies keyed on the length of the path.
                // This is done so that if we have two cookies with the same name,
                // we pass the cookie with the longest path first to the endpoint
                TreeMap cookieMap = new TreeMap();
                for (javax.servlet.http.Cookie cookie : cookies)
                {
                    CookieInfo origCookie = new CookieInfo(cookie.getName(), cookie.getDomain(), cookie.getName(),
                            cookie.getValue(), cookie.getPath(), cookie.getMaxAge(), null, cookie.getSecure());
                    CookieInfo newCookie = RequestUtil.createCookie(origCookie, context, context.getTarget().getUrl().getHost(),
                            context.getTarget().getUrl().getPath());

                    if (newCookie != null)
                    {
                        Integer pathInt = Integer.valueOf(0 - newCookie.path.length());
                        ArrayList list = (ArrayList) cookieMap.get(pathInt);
                        if (list == null)
                        {
                            list = new ArrayList();
                            cookieMap.put(pathInt, list);
                        }
                        list.add(newCookie);
                    }
                }

                // loop through (in order) the cookies we've gathered
                for (Object mapValue : cookieMap.values())
                {
                    ArrayList list = (ArrayList) mapValue;
                    for (Object aList : list)
                    {
                        CookieInfo cookieInfo = (CookieInfo) aList;
                        if (Log.isInfo())
                        {
                            String str = "-- Cookie in request: " + cookieInfo;
                            Log.getLogger(HTTPProxyService.LOG_CATEGORY).debug(str);
                        }

                        Cookie cookie = new Cookie(cookieInfo.domain, cookieInfo.name, cookieInfo.value, cookieInfo.path,
                                cookieInfo.maxAge, cookieInfo.secure);

                        // If this is a session cookie and we're dealing with local domain, make sure the session
                        // cookie has the latest session id. This check is needed when the session was invalidated
                        // and then recreated in this request; we shouldn't be sending the old session id to the endpoint.
                        if (context.isLocalDomain() && STRING_JSESSIONID.equalsIgnoreCase(cookieInfo.clientName))
                        {
                            FlexSession flexSession = FlexContext.getFlexSession();
                            if (flexSession != null && flexSession.isValid())
                            {
                                String sessionId = flexSession.getId();
                                String cookieValue = cookie.getValue();
                                if (!cookieValue.contains(sessionId))
                                {
                                    int colonIndex = cookieValue.indexOf(':');
                                    if (colonIndex != -1)
                                    {
                                        // Websphere changes jsession id to the following format:
                                        // 4 digit cacheId + jsessionId + ":" + cloneId.
                                        ServletContext servletContext = FlexContext.getServletContext();
                                        String serverInfo = servletContext != null ? servletContext.getServerInfo() : null;
                                        boolean isWebSphere = serverInfo != null && serverInfo.contains("WebSphere");
                                        if (isWebSphere)
                                        {
                                            String cacheId = cookieValue.substring(0, 4);
                                            String cloneId = cookieValue.substring(colonIndex);
                                            String wsSessionId = cacheId + sessionId + cloneId;
                                            cookie.setValue(wsSessionId);
                                        }
                                        else
                                        {
                                            cookie.setValue(sessionId);
                                        }
                                    }
                                    else
                                    {
                                        cookie.setValue(sessionId);
                                    }
                                }
                            }
                        }
                        // finally add the cookie to the current request
                        initState.addCookie(cookie);
                        context.addRequestCookie(cookie);
                    }
                }
            }
        }
    }

    /**
     * Copy HTTP request headers to the endpoint.
     * @param context the context
     */
    public static void copyHeadersToEndpoint(ProxyContext context)
    {
        HttpServletRequest clientRequest = FlexContext.getHttpRequest();
        if (clientRequest != null)
        {
            Enumeration headerNames = clientRequest.getHeaderNames();
            while (headerNames.hasMoreElements())
            {
                String headerName = (String)headerNames.nextElement();
                if (RequestUtil.ignoreHeader(headerName, context))
                {
                    continue;
                }

                Enumeration headers = clientRequest.getHeaders(headerName);
                while (headers.hasMoreElements())
                {
                    String value = (String)headers.nextElement();
                    context.getHttpMethod().addRequestHeader(headerName, value);

                    if (Log.isInfo())
                    {
                        Log.getLogger(HTTPProxyService.LOG_CATEGORY).debug("-- Header in request: " + headerName + " : " + value);
                    }
                }
            }
        }
    }

    /**
     * Add any custom headers.
     *
     * @param context the context
     */
    protected void addCustomHeaders(ProxyContext context)
    {
        HttpMethodBase httpMethod = context.getHttpMethod();

        String contentType = context.getContentType();
        if (contentType != null)
        {
            httpMethod.setRequestHeader(ProxyConstants.HEADER_CONTENT_TYPE, contentType);
        }

        Map customHeaders = context.getHeaders();
        if (customHeaders != null)
        {
            for (Object entry : customHeaders.entrySet())
            {

                String name = (String) ((Map.Entry) entry).getKey();
                Object value = ((Map.Entry) entry).getValue();
                if (value == null)
                {
                    httpMethod.setRequestHeader(name, "");
                }
                // Single value for the name.
                else if (value instanceof String)
                {
                    httpMethod.setRequestHeader(name, (String) value);
                }
                // Multiple values for the name.
                else if (value instanceof List)
                {
                    List valueList = (List) value;
                    for (Object currentValue : valueList)
                    {
                        if (currentValue == null)
                        {
                            httpMethod.addRequestHeader(name, "");
                        }
                        else
                        {
                            httpMethod.addRequestHeader(name, (String) currentValue);
                        }
                    }
                }
                else if (value.getClass().isArray())
                {
                    Object[] valueArray = (Object[]) value;
                    for (Object currentValue : valueArray)
                    {
                        if (currentValue == null)
                        {
                            httpMethod.addRequestHeader(name, "");
                        }
                        else
                        {
                            httpMethod.addRequestHeader(name, (String) currentValue);
                        }
                    }
                }
            }
        }

        if (context.isSoapRequest())
        {
            // add the appropriate headers
            context.getHttpMethod().setRequestHeader(ProxyConstants.HEADER_CONTENT_TYPE, MessageIOConstants.CONTENT_TYPE_XML);

            // get SOAPAction, and if it doesn't exist, create it
            String soapAction = null;

            Header header = context.getHttpMethod().getRequestHeader(MessageIOConstants.HEADER_SOAP_ACTION);
            if (header != null)
            {
                soapAction = header.getValue();
            }

            if (soapAction == null)
            {
                HttpServletRequest clientRequest = FlexContext.getHttpRequest();
                if (clientRequest != null)
                {
                    soapAction = clientRequest.getHeader(MessageIOConstants.HEADER_SOAP_ACTION);
                }

                // SOAPAction has to be quoted per the SOAP 1.1 spec.
                if (soapAction != null && !soapAction.startsWith("\"") && !soapAction.endsWith("\""))
                {
                    soapAction = "\"" + soapAction + "\"";
                }

                // If soapAction happens to still be null at this point, we'll end up not sending
                // one, which should generate a fault on the server side which we'll happily convey
                // back to the client.

                context.getHttpMethod().setRequestHeader(MessageIOConstants.HEADER_SOAP_ACTION, soapAction);
            }
        }
    }

    /**
     * Record the request headers in the proxy context.
     * @param context the context
     */
    protected void recordRequestHeaders(ProxyContext context)
    {
        if (context.getRecordHeaders())
        {
            Header[] headers = context.getHttpMethod().getRequestHeaders();
            if (headers != null)
            {
                HashMap recordedHeaders = new HashMap();
                for (Header header : headers)
                {
                    String headerName = header.getName();
                    String headerValue = header.getValue();
                    Object existingHeaderValue = recordedHeaders.get(headerName);
                    // Value(s) already exist for the header.
                    if (existingHeaderValue != null)
                    {
                        ArrayList headerValues;
                        // Only a single value exists.
                        if (existingHeaderValue instanceof String)
                        {
                            headerValues = new ArrayList();
                            headerValues.add(existingHeaderValue);
                            headerValues.add(headerValue);
                            recordedHeaders.put(headerName, headerValues);
                        }
                        // Multiple values exist.
                        else if (existingHeaderValue instanceof ArrayList)
                        {
                            headerValues = (ArrayList) existingHeaderValue;
                            headerValues.add(headerValue);
                        }
                    }
                    else
                    {
                        recordedHeaders.put(headerName, headerValue);
                    }
                }
                context.setRequestHeaders(recordedHeaders);
            }
        }
    }

    /**
     * Send the request.
     *
     * @param context the context
     */
    protected void sendRequest(ProxyContext context)
    {
        Target target = context.getTarget();
        String method = context.getMethod();
        HttpMethod httpMethod = context.getHttpMethod();
        final String BEGIN = "-- Begin ";
        final String END = "-- End ";
        final String REQUEST = " request --";

        if (httpMethod instanceof EntityEnclosingMethod)
        {
            Object data = processBody(context);
            Class dataClass = data.getClass();
            if (data instanceof String)
            {
                String requestString = (String)data;
                if (Log.isInfo())
                {
                    Logger logger = Log.getLogger(HTTPProxyService.LOG_CATEGORY);
                    logger.debug(BEGIN + method + REQUEST);
                    logger.debug(StringUtils.prettifyString(requestString));
                    logger.debug(END + method + REQUEST);
                }

                try
                {
                    StringRequestEntity requestEntity = new StringRequestEntity(requestString, null, "UTF-8");
                    ((EntityEnclosingMethod)httpMethod).setRequestEntity(requestEntity);
                }
                catch (UnsupportedEncodingException ex)
                {
                    ProxyException pe = new ProxyException(CAUGHT_ERROR);
                    pe.setDetails(CAUGHT_ERROR, "1", new Object[] { ex });
                    throw pe;
                }
            }
            else if (dataClass.isArray() && Byte.TYPE.equals(dataClass.getComponentType()))
            {
                byte[] dataBytes = (byte[])data;
                ByteArrayRequestEntity requestEntity = new ByteArrayRequestEntity(dataBytes, context.getContentType());
                ((EntityEnclosingMethod)httpMethod).setRequestEntity(requestEntity);
            }
            else if (data instanceof InputStream)
            {
                InputStreamRequestEntity requestEntity = new InputStreamRequestEntity((InputStream)data, context.getContentType());
                ((EntityEnclosingMethod)httpMethod).setRequestEntity(requestEntity);
            }
            //TODO: Support multipart post
            //else
            //{
                //FIXME: Throw exception if unhandled data type
            //}
        }
        else if (httpMethod instanceof GetMethod)
        {
            Object req = processBody(context);

            if (req instanceof String)
            {
                String requestString = (String)req;
                if (Log.isInfo())
                {
                    Logger logger = Log.getLogger(HTTPProxyService.LOG_CATEGORY);
                    logger.debug(BEGIN + method + REQUEST);
                    logger.debug(StringUtils.prettifyString(requestString));
                    logger.debug(END + method + REQUEST);
                }

                if (!"".equals(requestString))
                {
                    String query = context.getHttpMethod().getQueryString();
                    if (query != null)
                    {
                        query += "&" + requestString;
                    }
                    else
                    {
                        query = requestString;
                    }
                    context.getHttpMethod().setQueryString(query);
                }
            }
        }

        context.getHttpClient().setHostConfiguration(target.getHostConfig());

        try
        {
            context.getHttpClient().executeMethod(context.getHttpMethod());
        }
        catch (UnknownHostException uhex)
        {
            ProxyException pe = new ProxyException();
            pe.setMessage(UNKNOWN_HOST, new Object[] { uhex.getMessage() });
            pe.setCode(ProxyException.CODE_SERVER_PROXY_REQUEST_FAILED);
            throw pe;
        }
        catch (Exception ex)
        {
            // FIXME: JRB - could be more specific by looking for timeout and sending 504 in that case.
            // rfc2616 10.5.5 504 - could get more specific if we parse the HttpException
            ProxyException pe = new ProxyException(CAUGHT_ERROR);
            pe.setDetails(CAUGHT_ERROR, "1", new Object[] { ex.getMessage() });
            pe.setCode(ProxyException.CODE_SERVER_PROXY_REQUEST_FAILED);
            throw pe;
        }
    }

    /**
     * Process the request body and return its content.
     *
     * @param context the context
     * @return the body content
     */
    protected Object processBody(ProxyContext context)
    {
        //FIXME: Should we also send on URL params that were used to contact the message broker servlet?

        Object body = context.getBody();
        if (body == null)
        {
            return "";
        }
        else if (body instanceof String)
        {
            return body;
        }
        else if (body instanceof Map)
        {
            Map params = (Map)body;

            StringBuffer postData = new StringBuffer();

            boolean formValues = false;
            for (Object entry : params.entrySet())
            {
                String name = (String) ((Map.Entry)entry).getKey();
                if (!formValues)
                {
                    formValues = true;
                }
                else
                {
                    postData.append('&');
                }

                Object vals = ((Map.Entry)entry).getValue();

                if (vals == null)
                {
                    encodeParam(postData, name, "");
                }
                else if (vals instanceof String)
                {
                    String val = (String) vals;
                    encodeParam(postData, name, val);
                }
                else if (vals instanceof List)
                {
                    List valLists = (List) vals;

                    for (int i = 0; i < valLists.size(); i++)
                    {
                        Object o = valLists.get(i);
                        String val = "";
                        if (o != null)
                            val = o.toString();

                        if (i > 0)
                            postData.append('&');

                        encodeParam(postData, name, val);
                    }
                }
                else if (vals.getClass().isArray())
                {
                    for (int i = 0; i < Array.getLength(vals); i++)
                    {
                        Object o = Array.get(vals, i);
                        String val = "";
                        if (o != null)
                            val = o.toString();

                        if (i > 0)
                            postData.append('&');

                        encodeParam(postData, name, val);
                    }
                }
            }

            return postData.toString();
        }
        else if (body.getClass().isArray())
        {
            return body;
        }
        else if (body instanceof InputStream)
        {
            return body;
        }
        else
        {
            return body.toString();
        }
    }

    /**
     * Encode name=value in to a string buffer.
     *
     * @param buf buffer
     * @param name name
     * @param val value
     */
    protected void encodeParam(StringBuffer buf, String name, String val)
    {
        name = URLEncoder.encode(name);
        val = URLEncoder.encode(val);

        buf.append(name);
        buf.append('=');
        buf.append(val);
    }
}
