/*
 *  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.asyncweb.common;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.CharacterCodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TimeZone;

import org.apache.asyncweb.common.codec.HttpCodecUtils;
import org.apache.mina.core.buffer.IoBuffer;

/**
 * A default implementation of {@link MutableHttpRequest}.
 * 
 * @author The Apache MINA Project (dev@mina.apache.org)
 */
public class DefaultHttpRequest extends DefaultHttpMessage implements
        MutableHttpRequest {

    private static final long serialVersionUID = 3044997961372568928L;

    private HttpMethod method = HttpMethod.GET;
    private URI requestUri;
    private Map<String, List<String>> parameters = new HashMap<String, List<String>>();

    /**
     * Creates a new instance.
     */
    public DefaultHttpRequest() {
    }

    public void setCookies(String headerValue) {
        clearCookies();

        int version = -1; // -1 means version is not parsed yet.
        int fieldIdx = 0;
        MutableCookie currentCookie = null;

        StringTokenizer tk = new StringTokenizer(headerValue, ";,");

        while (tk.hasMoreTokens()) {
            String pair = tk.nextToken();
            String key;
            String value;

            int equalsPos = pair.indexOf('=');
            if (equalsPos >= 0) {
                key = pair.substring(0, equalsPos).trim();
                value = pair.substring(equalsPos + 1).trim();
            } else {
                key = pair.trim();
                value = "";
            }

            if (version < 0) {
                if (!key.equalsIgnoreCase("$Version")) {
                    // $Version is not specified.  Use the default (0).
                    version = 0;
                } else {
                    version = Integer.parseInt(value);
                    if (version != 0 && version != 1) {
                        throw new IllegalArgumentException("Invalid version: "
                                + version + " (" + headerValue + ")");
                    }
                }
            }

            if (version >= 0) {
                try {
                    switch (fieldIdx) {
                    case 1:
                        if (key.equalsIgnoreCase("$Path")) {
                            currentCookie.setPath(value);
                            fieldIdx++;
                        } else {
                            fieldIdx = 0;
                        }
                        break;
                    case 2:
                        if (key.equalsIgnoreCase("$Domain")) {
                            currentCookie.setDomain(value);
                            fieldIdx++;
                        } else {
                            fieldIdx = 0;
                        }
                        break;
                    case 3:
                        if (key.equalsIgnoreCase("$Port")) {
                            // Ignoring for now
                            fieldIdx++;
                        } else {
                            fieldIdx = 0;
                        }
                        break;
                    }
                } catch (NullPointerException e) {
                    throw new IllegalArgumentException(
                            "Cookie key-value pair not found (" + headerValue
                                    + ")");
                }

                if (fieldIdx == 0) {
                    currentCookie = new DefaultCookie(key);
                    currentCookie.setVersion(version);
                    currentCookie.setValue(value);
                    addCookie(currentCookie);
                    fieldIdx++;
                }
            }
        }
    }

    public URI getRequestUri() {
        return requestUri;
    }

    public void setRequestUri(URI requestUri) {
        if (requestUri == null) {
            throw new NullPointerException("requestUri");
        }
        this.requestUri = requestUri;
    }

    public boolean requiresContinuationResponse() {
        if (getProtocolVersion() == HttpVersion.HTTP_1_1) {
            String expectations = getHeader(HttpHeaderConstants.KEY_EXPECT);
            if (expectations != null) {
                return expectations
                        .indexOf(HttpHeaderConstants.VALUE_CONTINUE_EXPECTATION) >= 0;
            }
        }
        return false;
    }

    public HttpMethod getMethod() {
        return method;
    }

    public void setMethod(HttpMethod method) {
        if (method == null) {
            throw new NullPointerException("method");
        }
        this.method = method;
    }

    public void addParameter(String name, String value) {
        List<String> values = parameters.get(name);
        if (values == null) {
            values = new ArrayList<String>();
            parameters.put(name, values);
        }
        values.add(value);
    }

    public boolean removeParameter(String name) {
        return parameters.remove(name) != null;
    }

    public void setParameter(String name, String value) {
        List<String> values = new ArrayList<String>();
        values.add(value);
        parameters.put(name, values);
    }

    public void setParameters(Map<String, List<String>> parameters) {
        clearParameters();

        for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
            for (String value : entry.getValue()) {
                if (value == null) {
                    throw new NullPointerException("Parameter '"
                            + entry.getKey() + "' contains null.");
                }
            }
            if (entry.getValue().size() > 0) {
                this.parameters.put(entry.getKey(), entry.getValue());
            }
        }
    }

    public void setParameters(String queryString) {
        try {
            this.setParameters(queryString, HttpCodecUtils.DEFAULT_CHARSET_NAME);
        } catch (UnsupportedEncodingException e) {
            throw new InternalError(
                    HttpCodecUtils.DEFAULT_CHARSET_NAME +
                    " decoder must be provided by JDK.");
        }
    }

    public void setParameters(String queryString, String encoding)
            throws UnsupportedEncodingException {
        clearParameters();

        if (queryString == null || queryString.length() == 0) {
            return;
        }

        int pos = 0;
        while (pos < queryString.length()) {
            int ampPos = queryString.indexOf('&', pos);

            String value;
            if (ampPos < 0) {
                value = queryString.substring(pos);
                ampPos = queryString.length();
            } else {
                value = queryString.substring(pos, ampPos);
            }

            int equalPos = value.indexOf('=');
            if (equalPos < 0) {
                this.addParameter(URLDecoder.decode(value, encoding), "");
            } else {
                this.addParameter(URLDecoder.decode(value
                        .substring(0, equalPos), encoding), URLDecoder.decode(
                        value.substring(equalPos + 1), encoding));
            }

            pos = ampPos + 1;
        }
    }

    public void clearParameters() {
        this.parameters.clear();
    }

    public boolean containsParameter(String name) {
        return parameters.containsKey(name);
    }

    public String getParameter(String name) {
        List<String> values = parameters.get(name);
        if (values == null) {
            return null;
        }

        return values.get(0);
    }

    public Map<String, List<String>> getParameters() {
        return Collections.unmodifiableMap(parameters);
    }

    @Override
    public void setContent(IoBuffer content) {
        if (content == null) {
            throw new NullPointerException("content");
        }

        String ct = getContentType();
        if (ct != null && ct.toLowerCase().startsWith(HttpHeaderConstants.VALUE_URLENCODED_FORM.toLowerCase())) {
            content.mark();
            try {
                setParameters(content.getString(
                        HttpCodecUtils.DEFAULT_CHARSET.newDecoder()));
            } catch (CharacterCodingException e) {
                throw new IllegalArgumentException(
                        "Failed to decode the url-encoded content.", e);
            } finally {
                content.reset();
            }
        }
        super.setContent(content);
    }

    /**
     * Thread-local DateFormat for old-style cookies
     */
    private static final ThreadLocal<DateFormat> EXPIRY_FORMAT_LOACAL = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            SimpleDateFormat format = new SimpleDateFormat(
                    "EEE, dd-MMM-yyyy HH:mm:ss z", Locale.US);
            format.setTimeZone(TimeZone.getTimeZone(
                    HttpCodecUtils.DEFAULT_TIME_ZONE_NAME));
            return format;
        }

    };

    /**
     * A date long long ago, formatted in the old style cookie expire format
     */
    private static final String EXPIRED_DATE = getFormattedExpiry(0);

    private static String getFormattedExpiry(long time) {
        DateFormat format = EXPIRY_FORMAT_LOACAL.get();
        return format.format(new Date(time));
    }

    public void normalize() {
        // Encode parameters.
        Map<String, List<String>> params = getParameters();
        if (!params.isEmpty()) {
            try {
                boolean first = true;
                StringBuilder buf = new StringBuilder();
                for (Map.Entry<String, List<String>> e: params.entrySet()) {
                    if (e.getValue().isEmpty()) {
                        continue;
                    }
                    
                    for (String v: e.getValue()) {
                        if (!first) {
                            buf.append('&');
                        }
                        
                        buf.append(URLEncoder.encode(
                                e.getKey(), HttpCodecUtils.DEFAULT_CHARSET_NAME));
                        buf.append('=');
                        buf.append(URLEncoder.encode(
                                v, HttpCodecUtils.DEFAULT_CHARSET_NAME));
                        first = false;
                    }
                }
                
                if (buf.length() > 0) {
                    String uri = getRequestUri().toString();
                    int queryIndex = uri.indexOf('?');
                    switch (getMethod()) {
                    case POST:
                        if (queryIndex >= 0) {
                            setRequestUri(new URI(uri.substring(0, queryIndex)));
                        }
                        IoBuffer content = IoBuffer.allocate(buf.length());
                        content.put(buf.toString().getBytes(HttpCodecUtils.US_ASCII_CHARSET_NAME));
                        content.flip();
                        setContent(content);
                        setHeader(
                                HttpHeaderConstants.KEY_CONTENT_TYPE,
                                HttpHeaderConstants.VALUE_URLENCODED_FORM);
                        break;
                    default:
                        if (queryIndex >= 0) {
                            setRequestUri(new URI(
                                    uri.substring(0, queryIndex + 1) + buf));
                        } else {
                            setRequestUri(new URI(
                                    uri + '?' + buf));
                        }
                    }
                }
            } catch (Exception e) {
                throw (InternalError) new InternalError(
                        "Unexpected exception.").initCause(e);
            }
        }
        
        // Encode Cookies
        Set<Cookie> cookies = getCookies();
        if (!cookies.isEmpty()) {
            // Clear previous values.
            removeHeader(HttpHeaderConstants.KEY_COOKIE);
            
            // And encode.
            for (Cookie c: cookies) {
                StringBuilder buf = new StringBuilder();
                buf.append(c.getName());
                buf.append('=');
                buf.append(c.getValue());
                if (c.getVersion() > 0) {
                    buf.append("; version=");
                    buf.append(c.getVersion());
                }
                if (c.getPath() != null) {
                    buf.append("; path=");
                    buf.append(c.getPath());
                }
                
                long expiry = c.getMaxAge();
                int version = c.getVersion();
                if (expiry >= 0) {
                    if (version == 0) {
                        String expires = expiry == 0 ? EXPIRED_DATE
                                : getFormattedExpiry(System.currentTimeMillis()
                                        + 1000 * expiry);
                        buf.append("; Expires=");
                        buf.append(expires);
                    } else {
                        buf.append("; max-age=");
                        buf.append(c.getMaxAge());
                    }
                }
                
                if (c.isSecure()) {
                    buf.append("; secure");
                }
                if (c.isHttpOnly()) {
                   buf.append("; HTTPOnly");
                }
                
                buf.append(';');
                
                addHeader(HttpHeaderConstants.KEY_SET_COOKIE, buf.toString());
            }
        }
        
        // Add the Host header.
        if (!containsHeader(HttpHeaderConstants.KEY_HOST)) {
            URI uri = getRequestUri();
            String host = uri.getHost();
            if (host != null) {
                if ((uri.getScheme().equalsIgnoreCase("http") &&
                     uri.getPort() != 80 && uri.getPort() > 0) ||
                    (uri.getScheme().equalsIgnoreCase("https") &&
                     uri.getPort() != 443 && uri.getPort() > 0)) {
                    setHeader(HttpHeaderConstants.KEY_HOST, host + ':' + uri.getPort());
                } else {
                    setHeader(HttpHeaderConstants.KEY_HOST, host);
                }
            }
        }
        
        // Set Content-Length.
        if (!containsHeader(HttpHeaderConstants.KEY_TRANSFER_CODING)) {
            IoBuffer content = getContent();
            int contentLength = content == null? 0 : content.remaining();
            setHeader(
                    HttpHeaderConstants.KEY_CONTENT_LENGTH,
                    String.valueOf(contentLength));
        }
    }
}
