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

import java.util.List;
import java.util.Map;

import org.apache.asyncweb.common.Cookie;
import org.apache.asyncweb.common.DefaultCookie;
import org.apache.asyncweb.common.DefaultHttpResponse;
import org.apache.asyncweb.common.HttpHeaderConstants;
import org.apache.asyncweb.common.HttpResponse;
import org.apache.asyncweb.common.HttpResponseStatus;
import org.apache.asyncweb.common.HttpVersion;
import org.apache.asyncweb.common.MutableCookie;
import org.apache.asyncweb.common.MutableHttpResponse;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.filter.codec.ProtocolDecoderException;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.statemachine.ConsumeToEndOfSessionDecodingState;
import org.apache.mina.filter.codec.statemachine.CrLfDecodingState;
import org.apache.mina.filter.codec.statemachine.DecodingState;
import org.apache.mina.filter.codec.statemachine.DecodingStateMachine;
import org.apache.mina.filter.codec.statemachine.FixedLengthDecodingState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Parses HTTP requests.
 * Clients should register a <code>HttpRequestParserListener</code>
 * in order to receive notifications at important stages of request
 * building.<br/>
 *
 * <code>HttpRequestParser</code>s should not be built for each request
 * as each parser constructs an underlying state machine which is
 * relatively costly to build.<br/> Instead, parsers should be pooled.<br/>
 *
 * Note, however, that a parser <i>must</i> be <code>prepare</code>d before
 * each new parse.
 *
 * @author The Apache MINA Project (dev@mina.apache.org)
 */
abstract class HttpResponseDecodingState extends DecodingStateMachine {

    private static final Logger LOG = LoggerFactory
            .getLogger(HttpResponseDecodingState.class);

    /**
     * The header which provides a requests transfer coding
     */
    private static final String TRANSFER_CODING = "transfer-encoding";

    /**
     * The chunked coding
     */
    private static final String CHUNKED = "chunked";

    /**
     * The header which provides a requests content length
     */
    private static final String CONTENT_LENGTH = "Content-Length";

    /**
     * Indicates the start of a coding extension
     */
    private static final char EXTENSION_CHAR = ';';

    public static final String COOKIE_COMMENT = "comment";
    
    public static final String COOKIE_DOMAIN = "domain";
    
    public static final String COOKIE_EXPIRES = "expires";
    
    public static final String COOKIE_MAX_AGE = "max-age";
    
    public static final String COOKIE_PATH = "path";
    
    public static final String COOKIE_SECURE = "secure";
    
    public static final String COOKIE_VERSION = "version";

    /**
     * The request we are building
     */
    private MutableHttpResponse response;

    @Override
    protected DecodingState init() throws Exception {
        response = new DefaultHttpResponse();
        return SKIP_EMPTY_LINES;
    }

    @Override
    protected void destroy() throws Exception {
    }

    private final DecodingState SKIP_EMPTY_LINES = new CrLfDecodingState() {

        @Override
        protected DecodingState finishDecode(boolean foundCRLF,
                ProtocolDecoderOutput out) throws Exception {
            if (foundCRLF) {
                return this;
            } else {
                return READ_RESPONSE_LINE;
            }
        }
    };

    private final DecodingState READ_RESPONSE_LINE = new HttpResponseLineDecodingState() {
        @Override
        protected DecodingState finishDecode(List<Object> childProducts,
                ProtocolDecoderOutput out) throws Exception {
            if (childProducts.size() < 3) {
                // Session is closed.
                return null;
            }
            response.setProtocolVersion((HttpVersion) childProducts.get(0));
            final HttpResponseStatus status = HttpResponseStatus.forId((Integer) childProducts.get(1));
            if (status.isFinalResponse()) {
                response.setStatus(status);
                String reasonPhrase = (String) childProducts.get(2);
                if (reasonPhrase.length() > 0) {
                    response.setStatusReasonPhrase(reasonPhrase);
                }
                return READ_HEADERS;
            } else {
                return SKIP_HEADERS;
            }
        }
    };
    
    private final DecodingState SKIP_HEADERS = new HttpHeaderDecodingState() {
        @Override
        @SuppressWarnings("unchecked")
        protected DecodingState finishDecode(
                List<Object> childProducts, ProtocolDecoderOutput out) throws Exception {
            return READ_RESPONSE_LINE;
        }
    };


    private final DecodingState READ_HEADERS = new HttpHeaderDecodingState() {
        @Override
        @SuppressWarnings("unchecked")
        protected DecodingState finishDecode(List<Object> childProducts,
                ProtocolDecoderOutput out) throws Exception {
            Map<String, List<String>> headers = (Map<String, List<String>>) childProducts
                    .get(0);

            // Parse cookies
            List<String> cookies = headers.get(HttpHeaderConstants.KEY_SET_COOKIE);
            if (cookies != null && !cookies.isEmpty()) {
                for (String cookie : cookies) {
                    response.addCookie(parseCookie(cookie));
                }
            }
            response.setHeaders(headers);

            if (LOG.isDebugEnabled()) {
                LOG.debug("Decoded header: " + response.getHeaders());
            }

            // Select appropriate body decoding state.
            boolean isChunked = false;
            if (response.getProtocolVersion() == HttpVersion.HTTP_1_1) {
                LOG.debug("Request is HTTP 1/1. Checking for transfer coding");
                isChunked = isChunked(response);
            } else {
                LOG.debug("Request is not HTTP 1/1. Using content length");
            }
            DecodingState nextState;
            if (isChunked) {
                LOG.debug("Using chunked decoder for request");
                nextState = new ChunkedBodyDecodingState() {
                    @Override
                    protected DecodingState finishDecode(
                            List<Object> childProducts,
                            ProtocolDecoderOutput out) throws Exception {
                        if (childProducts.size() != 1) {
                            int chunkSize = 0;
                            for (Object product : childProducts) {
                                IoBuffer chunk = (IoBuffer) product;
                                chunkSize += chunk.remaining();
                            }

                            IoBuffer body = IoBuffer.allocate(chunkSize);
                            for (Object product : childProducts) {
                                IoBuffer chunk = (IoBuffer) product;
                                body.put(chunk);
                            }
                            body.flip();
                            response.setContent(body);
                        } else {
                            response.setContent((IoBuffer) childProducts.get(0));
                        }

                        out.write(response);
                        return null;
                    }
                };
            } else {
                int length = getContentLength(response);
                if (length > 0) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(
                                "Using fixed length decoder for request with " +
                                "length " + length);
                    }

                    // TODO max length limitation.
                    nextState = new FixedLengthDecodingState(length) {
                        @Override
                        protected DecodingState finishDecode(IoBuffer readData,
                                ProtocolDecoderOutput out) throws Exception {
                            response.setContent(readData);
                            out.write(response);
                            return null;
                        }
                    };
                } else if (length < 0) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(
                                "Using consume-to-disconnection decoder for " +
                                "request with unspecified length.");
                    }
                    // FIXME hard-coded max length.
                    nextState = new ConsumeToEndOfSessionDecodingState(1048576) {
                        @Override
                        protected DecodingState finishDecode(IoBuffer readData,
                                ProtocolDecoderOutput out) throws Exception {
                            response.setContent(readData);
                            out.write(response);
                            return null;
                        }
                    };
                } else {
                    LOG.debug("No entity body for this request");
                    out.write(response);
                    nextState = null;
                }
            }
            return nextState;
        }

        private Cookie parseCookie(String cookieHeader) throws DateParseException {

            MutableCookie cookie = null;

            String pairs[] = cookieHeader.split(";");
            for (int i = 0; i < pairs.length; i++) {
                String nameValue[] = pairs[i].trim().split("=");
                String name = nameValue[0].trim();
                String value = (nameValue.length == 2) ? nameValue[1].trim() : null;

                //First pair is the cookie name/value
                if (i == 0) {
                    cookie = new DefaultCookie(name, value);
                } else if (name.equalsIgnoreCase(COOKIE_COMMENT)) {
                    cookie.setComment(value);
                } else if (name.equalsIgnoreCase(COOKIE_PATH)) {
                    cookie.setPath(value);
                } else if (name.equalsIgnoreCase(COOKIE_SECURE)) {
                    cookie.setSecure(true);
                } else if (name.equalsIgnoreCase(COOKIE_VERSION)) {
                    cookie.setVersion(Integer.parseInt(value));
                } else if (name.equalsIgnoreCase(COOKIE_MAX_AGE)) {
                    int age = Integer.parseInt(value);
                    cookie.setMaxAge(age);
                } else if (name.equalsIgnoreCase(COOKIE_EXPIRES)) {
                    long createdDate = System.currentTimeMillis();
                    int age = (int)(DateUtil.parseDate(value).getTime() - createdDate) / 1000;
                    cookie.setCreatedDate(createdDate);
                    cookie.setMaxAge(age);
                } else if (name.equalsIgnoreCase(COOKIE_DOMAIN)) {
                    cookie.setDomain(value);
                }
            }

            return cookie;
        }

        /**
         * Obtains the content length from the specified request
         *
         * @param response  The request
         * @return         The content length, or -1 if not specified
         * @throws HttpDecoderException If an invalid content length is specified
         */
        private int getContentLength(HttpResponse response)
                throws ProtocolDecoderException {
            int length = -1;
            String lengthValue = response.getHeader(CONTENT_LENGTH);
            if (lengthValue != null) {
                try {
                    length = Integer.parseInt(lengthValue);
                } catch (NumberFormatException e) {
                    HttpCodecUtils.throwDecoderException(
                            "Invalid content length: " + length,
                            HttpResponseStatus.BAD_REQUEST);
                }
            }
            return length;
        }

        /**
         * Determines whether a specified request employs a chunked
         * transfer coding
         *
         * @param response  The request
         * @return         <code>true</code> iff the request employs a
         *                 chunked transfer coding
         * @throws HttpDecoderException
         *                 If the request employs an unsupported coding
         */
        private boolean isChunked(HttpResponse response)
                throws ProtocolDecoderException {
            boolean isChunked = false;
            String coding = response.getHeader(TRANSFER_CODING);
            if (coding != null) {
                int extensionIndex = coding.indexOf(EXTENSION_CHAR);
                if (extensionIndex != -1) {
                    coding = coding.substring(0, extensionIndex);
                }
                if (CHUNKED.equalsIgnoreCase(coding)) {
                    isChunked = true;
                } else {
                    // As we only support chunked encoding, any other encoding
                    // is unsupported
                    HttpCodecUtils.throwDecoderException(
                            "Unknown transfer coding " + coding,
                            HttpResponseStatus.NOT_IMPLEMENTED);
                }
            }
            return isChunked;
        }
    };
}
