/*
 * 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.ode.axis2.httpbinding;

import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.StatusLine;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpParams;
import org.apache.commons.httpclient.params.HostParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.ode.utils.Properties;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.http.HttpUtils;
import static org.apache.ode.utils.http.StatusCode.*;
import org.w3c.dom.Element;
import org.w3c.dom.Document;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Collections;

public class HttpHelper {

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


    public static void configure(HttpClient client, URI targetURI, Element authPart, HttpParams params) throws URIException {
        if (log.isDebugEnabled()) log.debug("Configuring http client...");

        /* Do not forget to wire params so that endpoint properties are passed around
           Down the road, when the request will be executed, the hierarchy of parameters will be the following:
             (-> means "is parent of")
             default params -> params from endpoint properties -> HttpClient -> HostConfig -> Method
           This wiring is done by HttpClient.
        */
        client.getParams().setDefaults(params);

        // Here we make sure HttpClient will not handle the default headers.
        // Actually HttpClient *appends* default headers while we want them to be ignored if the process assign them
        client.getParams().setParameter(HostParams.DEFAULT_HEADERS, Collections.EMPTY_LIST);

        // proxy configuration
        if (ProxyConf.isProxyEnabled(params, targetURI.getHost())) {
            if (log.isDebugEnabled()) log.debug("ProxyConf");
            ProxyConf.configure(client.getHostConfiguration(), client.getState(), (HttpTransportProperties.ProxyProperties) params.getParameter(Properties.PROP_HTTP_PROXY_PREFIX));
        }

        // security
        // ...

        // authentication
        /*
        We're expecting the following element:
        <xs:complexType name="credentialType">
            <xs:attribute name="scheme" type="xs:string" default="server-decide" />
            <xs:attribute name="username" type="xs:string" />
            <xs:attribute name="password" type="xs:string" />
        </xs:complexType>
        <xs:element type="rest_connector:credentialType" name="credentials" />
         */
        if (authPart != null) {
            // the part must be defined with an element, so take the fist child
            Element credentialsElement = DOMUtils.getFirstChildElement(authPart);
            if (credentialsElement != null && credentialsElement.getAttributes().getLength() != 0) {
                String scheme = DOMUtils.getAttribute(credentialsElement, "scheme");
                String username = DOMUtils.getAttribute(credentialsElement, "username");
                String password = DOMUtils.getAttribute(credentialsElement, "password");

                if (scheme != null
                        && !"server-decides".equalsIgnoreCase(scheme)
                        && !"basic".equalsIgnoreCase(scheme)
                        && !"digest".equalsIgnoreCase(scheme)) {
                    throw new IllegalArgumentException("Unknown Authentication scheme: [" + scheme + "] Accepted values are: Basic, Digest, Server-Decides");
                } else {
                    if(log.isDebugEnabled()) log.debug("credentials provided: scheme="+scheme+" user="+username+" password=********");
                    client.getState().setCredentials(
                            new AuthScope(targetURI.getHost(), targetURI.getPort(), AuthScope.ANY_REALM, scheme),
                            new UsernamePasswordCredentials(username, password));
                    // save one round trip if basic
                    client.getParams().setAuthenticationPreemptive("basic".equalsIgnoreCase(scheme));
                }
            }
        }
    }

    /**
     * Parse and convert a HTTP status line into an aml element.
     *
     * @param statusLine
     * @return
     * @throws HttpException
     * @see #statusLineToElement(org.w3c.dom.Document, org.apache.commons.httpclient.StatusLine)
     */
    public static Element statusLineToElement
            (String
                    statusLine) throws HttpException {
        return statusLineToElement(new StatusLine(statusLine));
    }

    public static Element statusLineToElement
            (StatusLine
                    statusLine) {
        return statusLineToElement(DOMUtils.newDocument(), statusLine);
    }

    /**
     * Convert a <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1">HTTP status line</a> into an xml element like this:
     * <p/>
     * < Status-line>
     * < HTTP-Version>HTTP/1.1< /HTTP-Version>
     * < Status-Code>200< /Status-Code>
     * < Reason-Phrase>Success - The action was successfully received, understood, and accepted< /Reason-Phrase>
     * < /Status-line></br>
     *
     * @param statusLine - the {@link org.apache.commons.httpclient.StatusLine} instance to be converted
     * @param doc        - the document to use to create new nodes
     * @return an Element
     */
    public static Element statusLineToElement
            (Document
                    doc, StatusLine
                    statusLine) {
        Element statusLineEl = doc.createElementNS(null, "Status-Line");
        Element versionEl = doc.createElementNS(null, "HTTP-Version");
        Element codeEl = doc.createElementNS(null, "Status-Code");
        Element reasonEl = doc.createElementNS(null, "Reason-Phrase");
        Element originalEl = doc.createElementNS(null, "original");

        // wiring
        doc.appendChild(statusLineEl);
        statusLineEl.appendChild(versionEl);
        statusLineEl.appendChild(codeEl);
        statusLineEl.appendChild(reasonEl);
        statusLineEl.appendChild(originalEl);

        // values
        versionEl.setTextContent(statusLine.getHttpVersion());
        codeEl.setTextContent(String.valueOf(statusLine.getStatusCode()));
        reasonEl.setTextContent(statusLine.getReasonPhrase());
        // the line as received, not parsed
        originalEl.setTextContent(statusLine.toString());

        return statusLineEl;
    }

    /**
     * Build a "details" element that looks like this:
     *
     * @param method
     * @return
     * @throws IOException
     */
    public static Element prepareDetailsElement
            (HttpMethod
                    method) {
        Header h = method.getResponseHeader("Content-Type");
        String receivedType = h != null ? h.getValue() : null;
        boolean bodyIsXml = receivedType != null && HttpUtils.isXml(receivedType);


        Document doc = DOMUtils.newDocument();
        Element detailsEl = doc.createElementNS(null, "details");
        Element statusLineEl = statusLineToElement(doc, method.getStatusLine());
        detailsEl.appendChild(statusLineEl);

        // set the body if any
        try {
            final String body = method.getResponseBodyAsString();
            if (StringUtils.isNotEmpty(body)) {
                Element bodyEl = doc.createElementNS(null, "responseBody");
                detailsEl.appendChild(bodyEl);
                // first, try to parse the body as xml
                // if it fails, put it as string in the body element
                boolean exceptionDuringParsing = false;
                if (bodyIsXml) {
                    try {
                        Element parsedBodyEl = DOMUtils.stringToDOM(body);
                        bodyEl.appendChild(doc.importNode(parsedBodyEl, true));
                    } catch (Exception e) {
                        String errmsg = "Unable to parse the response body as xml. Body will be inserted as string.";
                        if (log.isDebugEnabled()) log.debug(errmsg, e);
                        exceptionDuringParsing = true;
                    }
                }
                if (!bodyIsXml || exceptionDuringParsing) {
                    bodyEl.setTextContent(body);
                }
            }
        } catch (IOException e) {
            if (log.isWarnEnabled()) log.warn("Exception while loading response body", e);
        }
        return detailsEl;
    }

    private static final Pattern NON_LWS_PATTERN = Pattern.compile("\r\n([^\\s])");

    /**
     * This method ensures that a header value containing CRLF does not mess up the HTTP request.
     * Actually CRLF is the end-of-line marker for headers.
     * <p/>
     * To do so, all CRLF followed by a non-whitespace character are replaced by CRLF HT.
     * <p/>
     * This is possible because the
     * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2">Section 2.2</a> of HTTP standard (RFC2626) states that:
     * <p/>
     * <quote>
     * HTTP/1.1 header field values can be folded onto multiple lines if the
     * continuation line begins with a space or horizontal tab. All linear
     * white space, including folding, has the same semantics as SP. A
     * recipient MAY replace any linear white space with a single SP before
     * interpreting the field value or forwarding the message downstream.
     * <p/>
     * LWS            = [CRLF] 1*( SP | HT )
     * <p/>
     * </quote>
     * <p/>
     * FYI, HttpClient 3.x.x does not check this.
     *
     * @param header
     * @return the string properly ready to be used as an HTTP header field-content
     */
    public static String replaceCRLFwithLWS
            (String
                    header) {
        Matcher m = NON_LWS_PATTERN.matcher(header);
        StringBuffer sb = new StringBuffer(header.length());
        while (m.find()) {
            m.appendReplacement(sb, "\r\n\t");
            sb.append(m.group(1));
        }
        m.appendTail(sb);
        return sb.toString();
    }

    public static String requestToString
            (HttpMethod
                    m) {
        StringBuilder sb = new StringBuilder(256);
        try {
            sb.append("HTTP Request Details: \n").append(m.getName()).append(" ").append(m.getURI());
        } catch (URIException e) {
            // not that important
            if (log.isDebugEnabled()) log.debug(e);
        }
        sb.append("\nRequest Headers:");
        Header[] headers = m.getRequestHeaders();
        if (headers.length == 0) sb.append(" n/a");
        for (int i = 0; i < headers.length; i++) {
            Header h = headers[i];
            sb.append("\n\t").append(h.getName()).append(": ").append(h.getValue());
        }
        if (m instanceof EntityEnclosingMethod) {
            EntityEnclosingMethod eem = (EntityEnclosingMethod) m;
            if (eem.getRequestEntity() != null) {
                sb.append("\nRequest Entity:");
                sb.append("\n\tContent-Type:").append(eem.getRequestEntity().getContentType());
                sb.append("\n\tContent-Length:").append(eem.getRequestEntity().getContentLength());
                if (eem.getRequestEntity() instanceof StringRequestEntity) {
                    StringRequestEntity sre = (StringRequestEntity) eem.getRequestEntity();
                    sb.append("\n\tContent-Charset:").append(sre.getCharset());
                    sb.append("\n\tRequest Entity:\n").append(sre.getContent());
                }
            }
        }
        return sb.toString();
    }

    public static String responseToString
            (HttpMethod
                    m) {
        StringBuilder sb = new StringBuilder(256);
        try {
            sb.append("HTTP Response Details: \n").append(m.getName()).append(" ").append(m.getURI());
        } catch (URIException e) {
            // not that important
            if (log.isDebugEnabled()) log.debug(e);
        }
        sb.append("\nStatus-Line: ").append(m.getStatusLine());
        Header[] headers = m.getResponseHeaders();
        if (headers.length != 0) sb.append("\nResponse Headers: ");
        for (int i = 0; i < headers.length; i++) {
            Header h = headers[i];
            sb.append("\n\t").append(h.getName()).append(": ").append(h.getValue());
        }
        try {
            if (StringUtils.isNotEmpty(m.getResponseBodyAsString())) {
                sb.append("\nResponse Entity:\n").append(m.getResponseBodyAsString());
            }
        } catch (IOException e) {
            log.error(e);
        }
        Header[] footers = m.getResponseFooters();
        if (footers.length != 0) sb.append("\nResponse Footers: ");
        for (int i = 0; i < footers.length; i++) {
            Header h = footers[i];
            sb.append("\n\t").append(h.getName()).append(": ").append(h.getValue());
        }
        return sb.toString();
    }

    /**
     * @param s, the status code to test, must be in [400, 600[
     * @return 1 if fault, -1 if failure, 0 if undetermined
     */
    public static int isFaultOrFailure
            (
                    int s) {
        if (s < 400 || s >= 600) {
            throw new IllegalArgumentException("Status-Code must be in interval [400;600[");
        }
        if (s == _500_INTERNAL_SERVER_ERROR
                || s == _501_NOT_IMPLEMENTED
                || s == _502_BAD_GATEWAY
                || s == _505_HTTP_VERSION_NOT_SUPPORTED
                || s == _400_BAD_REQUEST
                || s == _402_PAYMENT_REQUIRED
                || s == _403_FORBIDDEN
                || s == _404_NOT_FOUND
                || s == _405_METHOD_NOT_ALLOWED
                || s == _406_NOT_ACCEPTABLE
                || s == _407_PROXY_AUTHENTICATION_REQUIRED
                || s == _409_CONFLICT
                || s == _410_GONE
                || s == _412_PRECONDITION_FAILED
                || s == _413_REQUEST_TOO_LONG
                || s == _414_REQUEST_URI_TOO_LONG
                || s == _415_UNSUPPORTED_MEDIA_TYPE
                || s == _411_LENGTH_REQUIRED
                || s == _416_REQUESTED_RANGE_NOT_SATISFIABLE
                || s == _417_EXPECTATION_FAILED) {
            return 1;
        } else if (s == _503_SERVICE_UNAVAILABLE
                || s == _504_GATEWAY_TIMEOUT
                || s == _401_UNAUTHORIZED
                || s == _408_REQUEST_TIMEOUT) {
            return -1;
        } else {
            return 0;
        }
    }
}
