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

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.http.api.DefaultHttpResponse;
import org.apache.mina.http.api.HttpEndOfContent;
import org.apache.mina.http.api.HttpStatus;
import org.apache.mina.http.api.HttpVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An HTTP decoder
 * 
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 */
public class HttpClientDecoder implements ProtocolDecoder {
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientCodec.class);
    
    /** Key for decoder current state */
    private static final String DECODER_STATE_ATT = "http.ds";

    /** Key for the partial HTTP requests head */
    private static final String PARTIAL_HEAD_ATT = "http.ph";

    /** Key for the number of bytes remaining to read for completing the body */
    private static final String BODY_REMAINING_BYTES = "http.brb";
    
    /** Key for indicating chunked data */
    private static final String BODY_CHUNKED = "http.ckd";
    
    /** Regex to parse HttpRequest Request Line */
    public static final Pattern REQUEST_LINE_PATTERN = Pattern.compile(" ");

    /** Regex to parse HttpRequest Request Line */
    public static final Pattern RESPONSE_LINE_PATTERN = Pattern.compile(" ");

    /** Regex to parse out QueryString from HttpRequest */
    public static final Pattern QUERY_STRING_PATTERN = Pattern.compile("\\?");

    /** Regex to parse out parameters from query string */
    public static final Pattern PARAM_STRING_PATTERN = Pattern.compile("\\&|;");

    /** Regex to parse out key/value pairs */
    public static final Pattern KEY_VALUE_PATTERN = Pattern.compile("=");

    /** Regex to parse raw headers and body */
    public static final Pattern RAW_VALUE_PATTERN = Pattern.compile("\\r\\n\\r\\n");

    /** Regex to parse raw headers from body */
    public static final Pattern HEADERS_BODY_PATTERN = Pattern.compile("\\r\\n");

    /** Regex to parse header name and value */
    public static final Pattern HEADER_VALUE_PATTERN = Pattern.compile(": ");

    /** Regex to split cookie header following RFC6265 Section 5.4 */
    public static final Pattern COOKIE_SEPARATOR_PATTERN = Pattern.compile(";");

    /**
     * {@inheritDoc}
     */
    @Override
    public void decode(IoSession session, IoBuffer msg, ProtocolDecoderOutput out) {
        DecoderState state = (DecoderState)session.getAttribute(DECODER_STATE_ATT);
        
        if (null == state) {
            session.setAttribute(DECODER_STATE_ATT, DecoderState.NEW);
            state = (DecoderState)session.getAttribute(DECODER_STATE_ATT);
        }
        
        switch (state) {
            case HEAD:
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("decoding HEAD");
                }
                
                // grab the stored a partial HEAD request
                ByteBuffer oldBuffer = (ByteBuffer)session.getAttribute(PARTIAL_HEAD_ATT);
                // concat the old buffer and the new incoming one
                IoBuffer.allocate(oldBuffer.remaining() + msg.remaining()).put(oldBuffer).put(msg).flip();
                // now let's decode like it was a new message
    
            case NEW:
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("decoding NEW");
                }
                
                DefaultHttpResponse rp = parseHttpReponseHead(msg.buf());
    
                if (rp == null) {
                    // we copy the incoming BB because it's going to be recycled by the inner IoProcessor for next reads
                    ByteBuffer partial = ByteBuffer.allocate(msg.remaining());
                    partial.put(msg.buf());
                    partial.flip();
                    // no request decoded, we accumulate
                    session.setAttribute(PARTIAL_HEAD_ATT, partial);
                    session.setAttribute(DECODER_STATE_ATT, DecoderState.HEAD);
                } else {
                    out.write(rp);
                    // is it a response with some body content ?
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("response with content");
                    }
                    
                    session.setAttribute(DECODER_STATE_ATT, DecoderState.BODY);
    
                    String contentLen = rp.getHeader("content-length");
    
                    if (contentLen != null) {
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug("found content len : {}", contentLen);
                        }
                        
                        session.setAttribute(BODY_REMAINING_BYTES, Integer.valueOf(contentLen));
                    } else if ("chunked".equalsIgnoreCase(rp.getHeader("transfer-encoding"))) {
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug("no content len but chunked");
                        }
                        
                        session.setAttribute(BODY_CHUNKED, Boolean.TRUE);
                    } else if ("close".equalsIgnoreCase(rp.getHeader("connection"))) {
                        session.closeNow();
                    } else {
                        throw new HttpException(HttpStatus.CLIENT_ERROR_LENGTH_REQUIRED, "no content length !");
                    }
                }
    
                break;
    
            case BODY:
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("decoding BODY: {} bytes", msg.remaining());
                }
                
                int chunkSize = msg.remaining();
                
                // send the chunk of body
                if (chunkSize != 0) {
                    IoBuffer wb = IoBuffer.allocate(msg.remaining());
                    wb.put(msg);
                    wb.flip();
                    out.write(wb);
                }
                
                msg.position(msg.limit());
                
                // do we have reach end of body ?
                int remaining;
                
                // if chunked, remaining is the msg.remaining()
                if( session.getAttribute(BODY_CHUNKED) != null ) {
                    remaining = chunkSize;
                } else {
                    // otherwise, manage with content-length
                    remaining = (Integer) session.getAttribute(BODY_REMAINING_BYTES);
                    remaining -= chunkSize;
                }
    
                if (remaining <= 0 ) {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("end of HTTP body");
                    }
                    
                    session.setAttribute(DECODER_STATE_ATT, DecoderState.NEW);
                    session.removeAttribute(BODY_REMAINING_BYTES);
                    
                    if( session.getAttribute(BODY_CHUNKED) != null ) {
                        session.removeAttribute(BODY_CHUNKED);
                    }
                    
                    out.write(new HttpEndOfContent());
                } else {
                    if( session.getAttribute(BODY_CHUNKED) == null ) {
                        session.setAttribute(BODY_REMAINING_BYTES, Integer.valueOf(remaining));
                    }
                }
    
                break;
    
            default:
                throw new HttpException(HttpStatus.SERVER_ERROR_INTERNAL_SERVER_ERROR, "Unknonwn decoder state : " + state);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void dispose(IoSession session) throws Exception {
    }

    private DefaultHttpResponse parseHttpReponseHead(ByteBuffer buffer) {
        String raw = new String(buffer.array(), 0, buffer.limit());
        String[] headersAndBody = RAW_VALUE_PATTERN.split(raw, -1);
        
        if (headersAndBody.length <= 1) {
            // we didn't receive the full HTTP head
            return null;
        }

        String[] headerFields = HEADERS_BODY_PATTERN.split(headersAndBody[0]);
        headerFields = ArrayUtil.dropFromEndWhile(headerFields, "");

        String requestLine = headerFields[0];
        Map<String, String> generalHeaders = new HashMap<>();

        for (String headerField:headerFields) {
            String[] header = HEADER_VALUE_PATTERN.split(headerField);
            generalHeaders.put(header[0].toLowerCase(), header[1]);
        }

        String[] elements = RESPONSE_LINE_PATTERN.split(requestLine);
        HttpStatus status = null;
        int statusCode = Integer.parseInt(elements[1]);
        
        for (HttpStatus httpStatus:HttpStatus.values()) {
            if (statusCode == httpStatus.code()) {
                
                break;
            }
        }
        
        HttpVersion version = HttpVersion.fromString(elements[0]);

        // we put the buffer position where we found the beginning of the HTTP body
        buffer.position(headersAndBody[0].length() + 4);

        return new DefaultHttpResponse(version, status, generalHeaders);
    }
}
