/*
 *  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.nio.charset.CharsetDecoder;

import org.apache.asyncweb.common.HttpResponseStatus;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.statemachine.ConsumeToDynamicTerminatorDecodingState;
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.apache.mina.filter.codec.statemachine.SkippingState;

/**
 * A decoder which decodes the body of HTTP Requests having
 * a "chunked" transfer-coding.
 *
 * This decoder does <i>not</i> decode trailing entity-headers - it simply
 * discards them. Tomcat currently does the same - so this is probably
 * the most stable approach for now.<br/>
 * If the need arises to decode them in the future, we simply need to employ a
 * <code>HttpHeaderDecoder</code> following the last chunk - yielding
 * headers for the encountered trailing entity-headers.<p/>
 *
 * This decoder decodes the following format:
 *
 * <pre>
 *      Chunked-Body   = *chunk
 *                       last-chunk
 *                       trailer
 *                       CRLF
 *      chunk          = chunk-size [ chunk-extension ] CRLF
 *                       chunk-data CRLF
 *      chunk-size     = 1*HEX
 *      last-chunk     = 1*("0") [ chunk-extension ] CRLF
 *      chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
 *      chunk-ext-name = token
 *      chunk-ext-val  = token | quoted-string
 *      chunk-data     = chunk-size(OCTET)
 *      trailer        = *(entity-header CRLF)
 * </pre>
 *
 * <code>ChunkedBodyDecoder</code> employs a <code>SharedBytesAllocator</code>
 * to enable the content of each decoded chunk to contribute to a single
 * <code>Bytes</code>. This enables all chunks to be read without requiring
 * copying.
 *
 * @author The Apache MINA Project (dev@mina.apache.org)
 * @version $Rev$, $Date$
 */
public abstract class ChunkedBodyDecodingState extends DecodingStateMachine {

    private final CharsetDecoder asciiDecoder =
        HttpCodecUtils.US_ASCII_CHARSET.newDecoder();

    private int lastChunkLength;
    private boolean chunkHasExtension;

    @Override
    protected void destroy() throws Exception {
    }

    @Override
    protected DecodingState init() throws Exception {
        chunkHasExtension = false;
        return READ_CHUNK_LENGTH;
    }

    private final DecodingState READ_CHUNK_LENGTH = new ConsumeToDynamicTerminatorDecodingState() {
        @Override
        protected DecodingState finishDecode(IoBuffer product,
                ProtocolDecoderOutput out) throws Exception {
            if (!product.hasRemaining()) {
                HttpCodecUtils
                        .throwDecoderException("Expected a chunk length.");
            }

            String length = product.getString(asciiDecoder).trim();
            lastChunkLength = Integer.parseInt(length, 16);
            if (chunkHasExtension) {
                return SKIP_CHUNK_EXTENSION;
            }
            return AFTER_SKIP_CHUNK_EXTENSION.decode(IoBuffer
                    .wrap(new byte[] { '\r' }), out);
        }

        @Override
        protected boolean isTerminator(byte b) {
            if (!(b >= '0' && b <= '9' || b >= 'a' && b <= 'f' || b >= 'A'
                && b <= 'F' || b == ' ')) {
                if (b == ' ' || b == '\r' || b == ';') {
                    chunkHasExtension = (b == ';' || b == ' ');
                    return true;
                }
                throw new IllegalArgumentException();
            }
            return false;
        }
    };

    private final DecodingState SKIP_CHUNK_EXTENSION = new SkippingState() {
        @Override
        protected DecodingState finishDecode(int skippedBytes) throws Exception {
            return AFTER_SKIP_CHUNK_EXTENSION;
        }

        @Override
        protected boolean canSkip(byte b) {
            return b != '\r';
        }
    };

    private final DecodingState AFTER_SKIP_CHUNK_EXTENSION = new CrLfDecodingState() {
        @Override
        protected DecodingState finishDecode(boolean foundCRLF,
                ProtocolDecoderOutput out) throws Exception {
            if (!foundCRLF) {
                HttpCodecUtils.throwDecoderException(
                        "Expected CRLF at the end of chunk extension.",
                        HttpResponseStatus.BAD_REQUEST);
            }

            if (lastChunkLength <= 0) {
                return FIND_END_OF_TRAILER;
            } else {
                return new FixedLengthDecodingState(lastChunkLength) {
                    @Override
                    protected DecodingState finishDecode(IoBuffer readData,
                            ProtocolDecoderOutput out) throws Exception {
                        out.write(readData);
                        // Reset the state.
                        lastChunkLength = 0;
                        return AFTER_CHUNK_DATA;
                    }
                };
            }
        }
    };

    private final DecodingState AFTER_CHUNK_DATA = new CrLfDecodingState() {
        @Override
        protected DecodingState finishDecode(boolean foundCRLF,
                ProtocolDecoderOutput out) throws Exception {
            if (!foundCRLF) {
                HttpCodecUtils.throwDecoderException(
                        "Expected CRLF after a chunk data.",
                        HttpResponseStatus.BAD_REQUEST);

            }
            chunkHasExtension = false;
            return READ_CHUNK_LENGTH;
        }
    };

    private final DecodingState FIND_END_OF_TRAILER = new CrLfDecodingState() {
        @Override
        protected DecodingState finishDecode(boolean foundCRLF,
                ProtocolDecoderOutput out) throws Exception {
            if (foundCRLF) {
                return null; // Finish
            } else {
                return SKIP_ENTITY_HEADER;
            }
        }
    };

    private final DecodingState SKIP_ENTITY_HEADER = new SkippingState() {

        @Override
        protected boolean canSkip(byte b) {
            return b != '\r';
        }

        @Override
        protected DecodingState finishDecode(int skippedBytes) throws Exception {
            return AFTER_SKIP_ENTITY_HEADER;
        }
    };

    private final DecodingState AFTER_SKIP_ENTITY_HEADER = new CrLfDecodingState() {
        @Override
        protected DecodingState finishDecode(boolean foundCRLF,
                ProtocolDecoderOutput out) throws Exception {
            return FIND_END_OF_TRAILER;
        }
    };
}
