// ========================================================================
// Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at 
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses. 
// ========================================================================
package org.eclipse.jetty.nested;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.http.AbstractGenerator;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpVersions;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

public class NestedGenerator extends AbstractGenerator
{
    private static final Logger LOG = Log.getLogger(NestedGenerator.class);

    final HttpServletResponse _response;
    final String _nestedIn;
    
    public NestedGenerator(Buffers buffers, EndPoint io, HttpServletResponse response, String nestedIn)
    {
        super(buffers,io);
        _response=response;
        _nestedIn=nestedIn;
    }

    public void addContent(Buffer content, boolean last) throws IOException
    {
        LOG.debug("addContent {} {}",content.length(),last);
        if (_noContent)
        {
            content.clear();
            return;
        }

        if (content.isImmutable())
            throw new IllegalArgumentException("immutable");

        if (_last || _state == STATE_END)
        {
            LOG.debug("Ignoring extra content {}", content);
            content.clear();
            return;
        }
        _last = last;

        if(!_endp.isOpen())
        {
            _state = STATE_END;
            return;
        }

        // Handle any unfinished business?
        if (_content != null && _content.length() > 0)
        {
            flushBuffer();
            if (_content != null && _content.length() > 0)
                throw new IllegalStateException("FULL");
        }

        _content = content;

        _contentWritten += content.length();

        // Handle the _content
        if (_head)
        {
            content.clear();
            _content = null;
        }
        else if (!last || _buffer!=null)
        {
            // Yes - so we better check we have a buffer
            initBuffer();
            // Copy _content to buffer;
            int len = 0;
            len = _buffer.put(_content);

            // make sure there is space for a trailing null   (???)
            if (len > 0 && _buffer.space() == 0)
            {
                len--;
                _buffer.setPutIndex(_buffer.putIndex() - 1);
            }
            
            LOG.debug("copied {} to buffer",len);

            _content.skip(len);

            if (_content.length() == 0)
                _content = null;
        }
    }

    public boolean addContent(byte b) throws IOException
    {
        // LOG.debug("addContent 1");
        if (_noContent)
            return false;

        if (_last || _state == STATE_END)
            throw new IllegalStateException("Closed");


        if(!_endp.isOpen())
        {
            _state = STATE_END;
            return false;
        }

        // Handle any unfinished business?
        if (_content != null && _content.length() > 0)
        {
            flushBuffer();
            if (_content != null && _content.length() > 0)
                throw new IllegalStateException("FULL");
        }

        _contentWritten++;

        // Handle the _content
        if (_head)
            return false;

        // we better check we have a buffer
        initBuffer();

        // Copy _content to buffer;

        _buffer.put(b);

        return _buffer.space() <= 1;
    }

    /* ------------------------------------------------------------ */
    private void initBuffer() throws IOException
    {
        if (_buffer == null)
        {
            // LOG.debug("initContent");
            _buffer = _buffers.getBuffer();
        }
    }

    /* ------------------------------------------------------------ */
    @Override
    public boolean isRequest()
    {
        return false;
    }

    /* ------------------------------------------------------------ */
    @Override
    public boolean isResponse()
    {
        return true;
    }

    /* ------------------------------------------------------------ */
    @Override
    public int prepareUncheckedAddContent() throws IOException
    {
        initBuffer();
        return _buffer.space();
    }

    /* ------------------------------------------------------------ */
    @Override
    public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
    {
        if (LOG.isDebugEnabled())
            LOG.debug("completeHeader: {}",fields.toString().trim().replace("\r\n","|"));
        if (_state != STATE_HEADER)
            return;

        if (_last && !allContentAdded)
            throw new IllegalStateException("last?");
        _last = _last | allContentAdded;

        if (_persistent==null)
            _persistent=(_version > HttpVersions.HTTP_1_0_ORDINAL);


        if (_reason == null)
            _response.setStatus(_status);
        else
            _response.setStatus(_status,_reason.toString());

        if (_status == 100 || _status == 204 || _status == 304)
        {
            _noContent = true;
            _content = null;
        }


        boolean has_server = false;
        if (fields != null)
        {
            // Add headers
            int s=fields.size();
            for (int f=0;f<s;f++)
            {
                HttpFields.Field field = fields.getField(f);
                if (field==null)
                    continue;
                _response.setHeader(field.getName(),field.getValue());
            }
        }

        if (!has_server && _status > 100 && getSendServerVersion())
            _response.setHeader(HttpHeaders.SERVER,"Jetty("+Server.getVersion()+",nested in "+_nestedIn+")");

        _state = STATE_CONTENT;
    }

    /* ------------------------------------------------------------ */
    /**
     * Complete the message.
     *
     * @throws IOException
     */
    @Override
    public void complete() throws IOException
    {
        if (_state == STATE_END)
            return;

        super.complete();

        if (_state < STATE_FLUSHING)
            _state = STATE_FLUSHING;

        flushBuffer();
    }

    /* ------------------------------------------------------------ */
    @Override
    public int flushBuffer() throws IOException
    {
        if (_state == STATE_HEADER)
            throw new IllegalStateException("State==HEADER");
        
        int len = 0;
        
        if (_buffer==null)
        {
            
            if (_content!=null && _content.length()>0)
            {
                // flush content directly
                len = _endp.flush(_content);
                if (len>0)
                    _content.skip(len);
            }
        }
        else
        {
            if (_buffer.length()==0 && _content!=null && _content.length()>0)
            {
                // Copy content to buffer
                _content.skip(_buffer.put(_content));
            }

            int size=_buffer.length();
            len =_endp.flush(_buffer);
            LOG.debug("flushBuffer {} of {}",len,size);
            if (len>0)
                _buffer.skip(len);
        }
        
        if (_content!=null && _content.length()==0)
            _content=null;
        if (_buffer!=null && _buffer.length()==0 && _content==null)
        {
            _buffers.returnBuffer(_buffer);
            _buffer=null;
        }
        
        if (_state==STATE_FLUSHING && _buffer==null && _content==null)
            _state=STATE_END;

        return len;
    }

}
