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

#include "BufferedInputStream.h"
#include <algorithm>

using namespace std;
using namespace decaf;
using namespace decaf::io;
using namespace decaf::lang;

////////////////////////////////////////////////////////////////////////////////
BufferedInputStream::BufferedInputStream( InputStream* stream, bool own )
: FilterInputStream( stream, own )
{
    // Default to a 1k buffer.
    init( 1024 );
}

////////////////////////////////////////////////////////////////////////////////
BufferedInputStream::BufferedInputStream( InputStream* stream,
    std::size_t bufferSize,
    bool own )
: FilterInputStream( stream, own )
{
    init( bufferSize );
}

////////////////////////////////////////////////////////////////////////////////
BufferedInputStream::~BufferedInputStream()
{
    // Destroy the buffer.
    if( buffer != NULL ){
        delete [] buffer;
        buffer = NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////
void BufferedInputStream::init( std::size_t bufferSize ){

    this->bufferSize = bufferSize;

    // Create the buffer and initialize the head and tail positions.
    buffer = new unsigned char[bufferSize];
    head = 0;
    tail = 0;
}

////////////////////////////////////////////////////////////////////////////////
unsigned char BufferedInputStream::read() throw ( IOException ){

    try{
        // If there's no data left, reset to pointers to the beginning of the
        // buffer.
        normalizeBuffer();

        // If we don't have any data buffered yet - read as much as
        // we can.
        if( isEmpty() ){

            // If we hit EOF without getting any Data, then throw IOException
            if( bufferData() == -1 ){
                throw IOException(
                    __FILE__, __LINE__,
                    "BufferedInputStream::read - EOF has been Reached");
            }
        }

        // Get the next character.
        char returnValue = buffer[head++];

        return returnValue;
    }
    DECAF_CATCH_RETHROW( IOException )
    DECAF_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
int BufferedInputStream::read( unsigned char* targetBuffer,
                               std::size_t targetBufferSize ) throw ( IOException ){

    try{

        // For zero, do nothing
        if( targetBufferSize == 0 ) {
            return 0;
        }

        // If there's no data left, reset to pointers to the beginning of the
        // buffer.
        normalizeBuffer();

        // If we still haven't filled the output buffer AND there is data
        // on the input stream to be read, read a buffer's worth from the stream.
        std::size_t totalRead = 0;
        while( totalRead < targetBufferSize ){

            // Get the remaining bytes to copy.
            std::size_t bytesToCopy = min( tail-head, (targetBufferSize-totalRead) );

            // Copy the data to the output buffer.
            memcpy( targetBuffer+totalRead, this->buffer+head, bytesToCopy );

            // Increment the total bytes read.
            totalRead += bytesToCopy;

            // Increment the head position.
            head += bytesToCopy;

            // If the buffer is now empty, reset the positions to the
            // head of the buffer.
            normalizeBuffer();

            // If we still haven't satisified the request,
            // read more data.
            if( totalRead < targetBufferSize ){

                // Buffer as much data as we can, return EOF if we hit it.
                if( bufferData() == -1 ) {
                    return -1;
                }
            }
        }

        // Return the total number of bytes read.
        return totalRead;
    }
    DECAF_CATCH_RETHROW( IOException )
    DECAF_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
std::size_t BufferedInputStream::skip( std::size_t num )
    throw ( IOException, lang::exceptions::UnsupportedOperationException ){

    try{
        // If there's no data left, reset to pointers to the beginning of the
        // buffer.
        normalizeBuffer();

        // loop until we've skipped the desired number of bytes
        std::size_t totalSkipped = 0;
        while( totalSkipped < num ){

            // Get the remaining bytes to copy.
            std::size_t bytesToSkip = min( tail-head, num-totalSkipped );

            // Increment the head position.
            head += bytesToSkip;

            // If the buffer is now empty, reset the positions to the
            // head of the buffer.
            normalizeBuffer();

            // If we still haven't satisified the request,
            // read more data.
            if( totalSkipped < num ){

                // Buffer as much data as we can.
                bufferData();
            }
        }

        // Return the total number of bytes read.
        return totalSkipped;
    }
    DECAF_CATCH_RETHROW( IOException )
    DECAF_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
int BufferedInputStream::bufferData() throw ( IOException ){

    try{
        if( getUnusedBytes() == 0 ){
            throw IOException( __FILE__, __LINE__,
                "BufferedInputStream::bufferData - buffer full" );
        }

        // Get the number of bytes currently available on the input stream
        // that could be read without blocking.
        std::size_t available = inputStream->available();

        // Calculate the number of bytes that we can read.  Always >= 1 byte!
        std::size_t bytesToRead = max( (std::size_t)1, min( available, getUnusedBytes() ) );

        // Read the bytes from the input stream.
        int bytesRead = inputStream->read( getTail(), bytesToRead );
        if( bytesRead == 0 ){
            throw IOException( __FILE__, __LINE__,
                "BufferedInputStream::read() - failed reading bytes from stream");
        }

        // Dont add -1 to tail if we hit EOF
        if( bytesRead == -1 ) {
            return bytesRead;
        }

        // Increment the tail to the new end position.
        tail += bytesRead;

        return bytesRead;
    }
    DECAF_CATCH_RETHROW( IOException )
    DECAF_CATCHALL_THROW( IOException )
}

