/*
 *   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.directory.mavibot.btree;


import java.io.IOException;
import java.io.Reader;


/**
 * Code taken from Harmony.
 * 
 * This modified class keep a track of the current position in the file,
 * whether the OS is linux/unix or Windows.
 * 
 * Wraps an existing {@link Reader} and <em>buffers</em> the input. Expensive
 * interaction with the underlying reader is minimized, since most (smaller)
 * requests can be satisfied by accessing the buffer alone. The drawback is that
 * some extra space is required to hold the buffer and that copying takes place
 * when filling that buffer, but this is usually outweighed by the performance
 * benefits.
 * 
 * <p/>A typical application pattern for the class looks like this:<p/>
 *
 * <pre>
 * BufferedReader buf = new BufferedReader(new FileReader(&quot;file.java&quot;));
 * </pre>
 * 
 * @see BufferedWriter
 * @since 1.1
 */
public class PositionBufferedReader extends Reader
{

    private Reader in;

    /**
     * The characters that can be read and refilled in bulk. We maintain three
     * indices into this buffer:<pre>
     *     { X X X X X X X X X X X X - - }
     *           ^     ^             ^
     *           |     |             |
     *         mark   pos           end</pre>
     * Pos points to the next readable character. End is one greater than the
     * last readable character. When {@code pos == end}, the buffer is empty and
     * must be {@link #fillBuf() filled} before characters can be read.
     *
     * <p>Mark is the value pos will be set to on calls to {@link #reset}. Its
     * value is in the range {@code [0...pos]}. If the mark is {@code -1}, the
     * buffer cannot be reset.
     *
     * <p>MarkLimit limits the distance between the mark and the pos. When this
     * limit is exceeded, {@link #reset} is permitted (but not required) to
     * throw an exception. For shorter distances, {@link #reset} shall not throw
     * (unless the reader is closed).
     */
    private char[] buf;

    private int pos;

    private int end;

    private int mark = -1;

    private int markLimit = -1;
    
    /** The current position in the file */
    private long filePos;


    /**
     * Constructs a new BufferedReader on the Reader {@code in}. The
     * buffer gets the default size (8 KB).
     * 
     * @param in
     *            the Reader that is buffered.
     */
    public PositionBufferedReader( Reader in )
    {
        super( in );
        this.in = in;
        buf = new char[8192];
    }


    /**
     * Closes this reader. This implementation closes the buffered source reader
     * and releases the buffer. Nothing is done if this reader has already been
     * closed.
     * 
     * @throws IOException
     *             if an error occurs while closing this reader.
     */
    @Override
    public void close() throws IOException
    {
        synchronized ( lock )
        {
            if ( !isClosed() )
            {
                in.close();
                buf = null;
            }
        }
    }


    /**
     * Populates the buffer with data. It is an error to call this method when
     * the buffer still contains data; ie. if {@code pos < end}.
     *
     * @return the number of bytes read into the buffer, or -1 if the end of the
     *      source stream has been reached.
     */
    private int fillBuf() throws IOException
    {
        // assert(pos == end);

        if ( mark == -1 || ( pos - mark >= markLimit ) )
        {
            /* mark isn't set or has exceeded its limit. use the whole buffer */
            int result = in.read( buf, 0, buf.length );
            if ( result > 0 )
            {
                mark = -1;
                pos = 0;
                end = result;
            }
            return result;
        }

        if ( mark == 0 && markLimit > buf.length )
        {
            /* the only way to make room when mark=0 is by growing the buffer */
            int newLength = buf.length * 2;
            if ( newLength > markLimit )
            {
                newLength = markLimit;
            }
            char[] newbuf = new char[newLength];
            System.arraycopy( buf, 0, newbuf, 0, buf.length );
            buf = newbuf;
        }
        else if ( mark > 0 )
        {
            /* make room by shifting the buffered data to left mark positions */
            System.arraycopy( buf, mark, buf, 0, buf.length - mark );
            pos -= mark;
            end -= mark;
            mark = 0;
        }

        /* Set the new position and mark position */
        int count = in.read( buf, pos, buf.length - pos );
        if ( count != -1 )
        {
            end += count;
        }
        return count;
    }


    /**
     * Indicates whether or not this reader is closed.
     * 
     * @return {@code true} if this reader is closed, {@code false}
     *         otherwise.
     */
    private boolean isClosed()
    {
        return buf == null;
    }


    /**
     * Reads at most {@code length} characters from this reader and stores them
     * at {@code offset} in the character array {@code buffer}. Returns the
     * number of characters actually read or -1 if the end of the source reader
     * has been reached. If all the buffered characters have been used, a mark
     * has not been set and the requested number of characters is larger than
     * this readers buffer size, BufferedReader bypasses the buffer and simply
     * places the results directly into {@code buffer}.
     * 
     * @param buffer
     *            the character array to store the characters read.
     * @param offset
     *            the initial position in {@code buffer} to store the bytes read
     *            from this reader.
     * @param length
     *            the maximum number of characters to read, must be
     *            non-negative.
     * @return number of characters read or -1 if the end of the source reader
     *         has been reached.
     * @throws IndexOutOfBoundsException
     *             if {@code offset < 0} or {@code length < 0}, or if
     *             {@code offset + length} is greater than the size of
     *             {@code buffer}.
     * @throws IOException
     *             if this reader is closed or some other I/O error occurs.
     */
    @Override
    public int read( char[] buffer, int offset, int length ) throws IOException
    {
        synchronized ( lock )
        {
            if ( isClosed() )
            {
                throw new IOException( "" ); //$NON-NLS-1$
            }
            if ( offset < 0 || offset > buffer.length - length || length < 0 )
            {
                throw new IndexOutOfBoundsException();
            }
            int outstanding = length;
            while ( outstanding > 0 )
            {

                /*
                 * If there are bytes in the buffer, grab those first.
                 */
                int available = end - pos;
                if ( available > 0 )
                {
                    int count = available >= outstanding ? outstanding : available;
                    System.arraycopy( buf, pos, buffer, offset, count );
                    pos += count;
                    offset += count;
                    outstanding -= count;
                }

                /*
                 * Before attempting to read from the underlying stream, make
                 * sure we really, really want to. We won't bother if we're
                 * done, or if we've already got some bytes and reading from the
                 * underlying stream would block.
                 */
                if ( outstanding == 0 || ( outstanding < length && !in.ready() ) )
                {
                    break;
                }

                // assert(pos == end);

                /*
                 * If we're unmarked and the requested size is greater than our
                 * buffer, read the bytes directly into the caller's buffer. We
                 * don't read into smaller buffers because that could result in
                 * a many reads.
                 */
                if ( ( mark == -1 || ( pos - mark >= markLimit ) )
                    && outstanding >= buf.length )
                {
                    int count = in.read( buffer, offset, outstanding );
                    if ( count > 0 )
                    {
                        offset += count;
                        outstanding -= count;
                        mark = -1;
                    }

                    break; // assume the source stream gave us all that it could
                }

                if ( fillBuf() == -1 )
                {
                    break; // source is exhausted
                }
            }

            int count = length - outstanding;
            return ( count > 0 || count == length ) ? count : -1;
        }
    }


    /**
     * Returns the next line of text available from this reader. A line is
     * represented by zero or more characters followed by {@code '\n'},
     * {@code '\r'}, {@code "\r\n"} or the end of the reader. The string does
     * not include the newline sequence.
     * 
     * @return the contents of the line or {@code null} if no characters were
     *         read before the end of the reader has been reached.
     * @throws IOException
     *             if this reader is closed or some other I/O error occurs.
     */
    public String readLine() throws IOException
    {
        synchronized ( lock )
        {
            if ( isClosed() )
            {
                throw new IOException( "File closed, cannot read from it" );
            }
            
            /* has the underlying stream been exhausted? */
            if ( pos == end && fillBuf() == -1 )
            {
                return null;
            }
            
            for ( int charPos = pos; charPos < end; charPos++ )
            {
                char ch = buf[charPos];
                
                if ( ch > '\r' )
                {
                    filePos++;
                    continue;
                }

                if ( ch == '\n' )
                {
                    String res = new String( buf, pos, charPos - pos );
                    pos = charPos + 1;
                    filePos++;

                    return res;
                }
                else if ( ch == '\r' )
                {
                    String res = new String( buf, pos, charPos - pos );
                    filePos++;
                    pos = charPos + 1;

                    if ( ( ( pos < end ) || ( fillBuf() != -1 ) )
                        && ( buf[pos] == '\n' ) )
                    {
                        filePos++;
                        pos++;
                    }

                    return res;
                }
            }

            char eol = '\0';
            StringBuilder result = new StringBuilder( 80 );
            /* Typical Line Length */

            result.append( buf, pos, end - pos );

            while ( true )
            {
                pos = end;

                /* Are there buffered characters available? */
                if ( eol == '\n' )
                {
                    return result.toString();
                }
                
                // attempt to fill buffer
                if ( fillBuf() == -1 )
                {
                    // characters or null.
                    return result.length() > 0 || eol != '\0'
                        ? result.toString()
                        : null;
                }

                filePos--;

                for ( int charPos = pos; charPos < end; charPos++ )
                {
                    char c = buf[charPos];
                    filePos++;
                    
                    if ( eol == '\0' )
                    {
                        if ( ( c == '\n' || c == '\r' ) )
                        {
                            eol = c;
                        }
                    }
                    else if ( eol == '\r' && c == '\n' )
                    {
                        if ( charPos > pos )
                        {
                            result.append( buf, pos, charPos - pos - 1 );
                        }

                        pos = charPos + 1;
                        
                        return result.toString();
                    }
                    else
                    {
                        if ( charPos > pos )
                        {
                            result.append( buf, pos, charPos - pos - 1 );
                        }

                        pos = charPos;
                        
                        return result.toString();
                    }
                }
                
                if ( eol == '\0' )
                {
                    result.append( buf, pos, end - pos );
                }
                else
                {
                    result.append( buf, pos, end - pos - 1 );
                }
            }
        }
    }


    /**
     * @return the filePos
     */
    public long getFilePos()
    {
        return filePos;
    }
}