/*
 * 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 org.apache.axis2.builder;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.java.security.AccessController;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisBinding;
import org.apache.axis2.description.AxisBindingOperation;
import org.apache.axis2.description.AxisEndpoint;
import org.apache.axis2.description.WSDL20DefaultValueHolder;
import org.apache.axis2.description.WSDL2Constants;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.transport.http.util.URIEncoderDecoder;
import org.apache.axis2.util.MultipleEntryHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;


public class XFormURLEncodedBuilder implements Builder {

    private static final Log log = LogFactory.getLog(XFormURLEncodedBuilder.class);

    /**
     * @return Returns the document element.
     */
    public OMElement processDocument(InputStream inputStream, String contentType,
                                     MessageContext messageContext)
            throws AxisFault {

        MultipleEntryHashMap parameterMap = new MultipleEntryHashMap();
        SOAPFactory soapFactory;
        AxisBindingOperation axisBindingOperation =
                (AxisBindingOperation) messageContext.getProperty(
                        Constants.AXIS_BINDING_OPERATION);
        String queryParameterSeparator = null;
        String templatedPath = null;
        if (axisBindingOperation != null) {
            queryParameterSeparator = (String) axisBindingOperation
                    .getProperty(WSDL2Constants.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR);
            templatedPath =
                    (String) axisBindingOperation.getProperty(WSDL2Constants.ATTR_WHTTP_LOCATION);
        }
        if (queryParameterSeparator == null) {
            queryParameterSeparator =
                    WSDL20DefaultValueHolder.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR_DEFAULT;
        }

        AxisEndpoint axisEndpoint =
                (AxisEndpoint) messageContext.getProperty(WSDL2Constants.ENDPOINT_LOCAL_NAME);
        if (axisEndpoint != null) {
            AxisBinding axisBinding = axisEndpoint.getBinding();
            String soapVersion =
                    (String) axisBinding.getProperty(WSDL2Constants.ATTR_WSOAP_VERSION);
            soapFactory = getSOAPFactory(soapVersion);
        } else {
            soapFactory = getSOAPFactory(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
        }
        EndpointReference endpointReference = messageContext.getTo();
        if (endpointReference == null) {
            throw new AxisFault("Cannot create DocumentElement without destination EPR");
        }

        String requestURL = endpointReference.getAddress();
        try {
            requestURL = extractParametersUsingHttpLocation(templatedPath, parameterMap,
                                                            requestURL,
                                                            queryParameterSeparator);
        } catch (UnsupportedEncodingException e) {
            throw AxisFault.makeFault(e);
        }

        String query = requestURL;
        int index;
        if ((index = requestURL.indexOf("?")) > -1) {
            query = requestURL.substring(index + 1);
        }

        extractParametersFromRequest(parameterMap, query, queryParameterSeparator,
                                     (String) messageContext.getProperty(
                                             Constants.Configuration.CHARACTER_SET_ENCODING),
                                     inputStream);


        return BuilderUtil.buildsoapMessage(messageContext, parameterMap,
                                            soapFactory);
    }

    protected void extractParametersFromRequest(MultipleEntryHashMap parameterMap,
                                                String query,
                                                String queryParamSeparator,
                                                final String charsetEncoding,
                                                final InputStream inputStream)
            throws AxisFault {

        if (query != null && !"".equals(query)) {

            String parts[] = query.split(queryParamSeparator);
            for (int i = 0; i < parts.length; i++) {
                int separator = parts[i].indexOf("=");
                if (separator > 0) {
                    String value = parts[i].substring(separator + 1);
                    try {
                        value = URIEncoderDecoder.decode(value);
                    } catch (UnsupportedEncodingException e) {
                        throw AxisFault.makeFault(e);
                    }

                    parameterMap
                            .put(parts[i].substring(0, separator),
                                 value);
                }
            }

        }

        if (inputStream != null) {
            try {
                InputStreamReader inputStreamReader =
                        null;
                try {
                    inputStreamReader = (InputStreamReader) AccessController.doPrivileged(
                            new PrivilegedExceptionAction() {
                                public Object run() throws UnsupportedEncodingException {
                                    return new InputStreamReader(inputStream, charsetEncoding);
                                }
                            }
                    );
                } catch (PrivilegedActionException e) {
                    throw (UnsupportedEncodingException) e.getException();
                }
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                while (true) {
                    String line = bufferedReader.readLine();
                    if (line != null) {
                        String parts[] = line.split(
                                WSDL20DefaultValueHolder.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR_DEFAULT);
                        for (int i = 0; i < parts.length; i++) {
                            int separator = parts[i].indexOf("=");
                            String value = parts[i].substring(separator + 1);
                            parameterMap.put(parts[i].substring(0, separator),
                                             URIEncoderDecoder.decode(value));
                        }
                    } else {
                        break;
                    }
                }
            } catch (IOException e) {
                throw AxisFault.makeFault(e);
            }
        }
    }

    /**
     * Here is what I will try to do here. I will first try to identify the location of the first
     * template element in the request URI. I am trying to deduce the location of that location
     * using the httpLocation element of the binding (it is passed in to this
     * method).
     * If there is a contant part in the httpLocation, then I will identify it. For this, I get
     * the index of {, from httpLocation param, and whatever to the left of it is the contant part.
     * Then I search for this constant part inside the url. This will give us the access to the first
     * template parameter.
     * To find the end of this parameter, we need to get the index of the next constant, from
     * httpLocation attribute. Likewise we keep on discovering parameters.
     * <p/>
     * Assumptions :
     * 1. User will always append the value of httpLocation to the address given in the
     * endpoint.
     * 2. I was talking about the constants in the httpLocation. Those constants will not occur,
     * to a reasonable extend, before the constant we are looking for.
     *
     * @param templatedPath
     * @param parameterMap
     */
    protected String extractParametersUsingHttpLocation(String templatedPath,
                                                        MultipleEntryHashMap parameterMap,
                                                        String requestURL,
                                                        String queryParameterSeparator)
            throws AxisFault, UnsupportedEncodingException {


        if (templatedPath != null && !"".equals(templatedPath) && templatedPath.indexOf("{") > -1) {
            StringBuffer pathTemplate = new StringBuffer(templatedPath);

            // this will hold the index, from which we need to process the request URI
            int startIndex = 0;
            int templateStartIndex = 0;
            int templateEndIndex = 0;
            int indexOfNextConstant = 0;

            StringBuffer requestURIBuffer = new StringBuffer(requestURL);

            while (startIndex < requestURIBuffer.length()) {
                // this will always hold the starting index of a template parameter
                templateStartIndex = pathTemplate.indexOf("{", templateStartIndex);

                if (templateStartIndex > 0) {
                    // get the preceding constant part from the template
                    String constantPart =
                            pathTemplate.substring(templateEndIndex + 1, templateStartIndex);
                    constantPart = constantPart.replaceAll("\\{\\{","{");
                    constantPart = constantPart.replaceAll("}}","}");

                    // get the index of the end of this template param
                    templateEndIndex = pathTemplate.indexOf("}", templateStartIndex);
                    if ((pathTemplate.length() -1) > templateEndIndex && pathTemplate.charAt(templateEndIndex +1) == '}') {
                        templateEndIndex = pathTemplate.indexOf("}", templateEndIndex +2);
                    }

                    String parameterName =
                            pathTemplate.substring(templateStartIndex + 1, templateEndIndex);
                    // next try to find the next constant
                    templateStartIndex = pathTemplate.indexOf("{", templateEndIndex);
                    if (pathTemplate.charAt(templateStartIndex +1) == '{') {
                        templateStartIndex = pathTemplate.indexOf("{", templateStartIndex +2);
                    }

                    int endIndexOfConstant = requestURIBuffer
                            .indexOf(constantPart, indexOfNextConstant) + constantPart.length();

                    if (templateStartIndex == -1) {
                        if (templateEndIndex == pathTemplate.length() - 1) {

                            // We may have occations where we have templates of the form foo/{name}.
                            // In this case the next connstant will be ? and not the
                            // queryParameterSeparator
                            indexOfNextConstant =
                                    requestURIBuffer
                                            .indexOf("?", endIndexOfConstant);
                            if (indexOfNextConstant == -1) {
                                indexOfNextConstant =
                                        requestURIBuffer
                                                .indexOf(queryParameterSeparator,
                                                         endIndexOfConstant);
                            }
                            if (indexOfNextConstant > 0) {
                                addParameterToMap(parameterMap, parameterName,
                                                  requestURIBuffer.substring(endIndexOfConstant,
                                                                             indexOfNextConstant));
                                return requestURL.substring(indexOfNextConstant);
                            } else {

                                addParameterToMap(parameterMap, parameterName,
                                                  requestURIBuffer.substring(
                                                          endIndexOfConstant));
                                return "";
                            }

                        } else {

                            constantPart =
                                    pathTemplate.substring(templateEndIndex + 1,
                                                           pathTemplate.length());
                            constantPart = constantPart.replaceAll("\\{\\{","{");
                            constantPart = constantPart.replaceAll("}}","}");
                            indexOfNextConstant =
                                    requestURIBuffer.indexOf(constantPart, endIndexOfConstant);

                            addParameterToMap(parameterMap, parameterName,
                                              requestURIBuffer.substring(
                                                      endIndexOfConstant, indexOfNextConstant));

                            if (requestURIBuffer.length() > indexOfNextConstant + 1) {
                                return requestURIBuffer.substring(indexOfNextConstant + 1);
                            }
                            return "";
                        }
                    } else {

                        // this is the next constant from the template
                        constantPart =
                                pathTemplate
                                        .substring(templateEndIndex + 1, templateStartIndex);
                        constantPart = constantPart.replaceAll("\\{\\{","{");
                        constantPart = constantPart.replaceAll("}}","}");

                        indexOfNextConstant =
                                requestURIBuffer.indexOf(constantPart, endIndexOfConstant);
                        addParameterToMap(parameterMap, parameterName, requestURIBuffer.substring(
                                endIndexOfConstant, indexOfNextConstant));
                        startIndex = indexOfNextConstant;

                    }

                }

            }
        }

        return requestURL;
    }

    private void addParameterToMap(MultipleEntryHashMap parameterMap, String paramName,
                                   String paramValue)
            throws UnsupportedEncodingException, AxisFault {
        try {
            paramValue = URIEncoderDecoder.decode(paramValue);
        } catch (UnsupportedEncodingException e) {
            throw AxisFault.makeFault(e);
        }
        if (paramName.startsWith(WSDL2Constants.TEMPLATE_ENCODE_ESCAPING_CHARACTER)) {
            parameterMap.put(paramName.substring(1), paramValue);
        } else {
            parameterMap.put(paramName, paramValue);
        }

    }

    private SOAPFactory getSOAPFactory(String nsURI) throws AxisFault {
        if (nsURI == null) {
            return OMAbstractFactory.getSOAP12Factory();
        }
        else if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(nsURI)) {
            return OMAbstractFactory.getSOAP12Factory();
        } else if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(nsURI)) {
            return OMAbstractFactory.getSOAP11Factory();
        } else {
            throw new AxisFault(Messages.getMessage("invalidSOAPversion"));
        }
    }
}