/*
 * 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 tests.support;

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

public class Support_StringReader extends Reader {
    private String str;

    private int markpos = -1;

    private int pos = 0;

    private int count;

    /**
     * Construct a StringReader on the String <code>str</code>. The size of
     * the reader is set to the <code>length()</code> of the String and the
     * Object to synchronize access through is set to <code>str</code>.
     *
     * @param str
     *            the String to filter reads on.
     */
    public Support_StringReader(String str) {
        super(str);
        this.str = str;
        this.count = str.length();
    }

    /**
     * This method closes this StringReader. Once it is closed, you can no
     * longer read from it. Only the first invocation of this method has any
     * effect.
     *
     */
    @Override
    public void close() {
        synchronized (lock) {
            if (isOpen()) {
                str = null;
            }
        }
    }

    /**
     * Answer a boolean indicating whether or not this StringReader is open.
     */
    private boolean isOpen() {
        return str != null;
    }

    /**
     * Set a Mark position in this Reader. The parameter <code>readLimit</code>
     * is ignored for StringReaders. Sending reset() will reposition the reader
     * back to the marked position provided the mark has not been invalidated.
     *
     * @param readlimit
     *            ignored for StringReaders.
     *
     * @exception java.io.IOException
     *                If an error occurs attempting mark this StringReader.
     */
    @Override
    public void mark(int readLimit) throws IOException {
        if (readLimit >= 0) {
            synchronized (lock) {
                if (isOpen()) {
                    markpos = pos;
                } else {
                    throw new IOException("StringReader is closed");
                }
            }
        } else {
            throw new IllegalArgumentException();
        }
    }

    /**
     * Answers a boolean indicating whether or not this StringReader supports
     * mark() and reset(). This method always returns true.
     *
     * @return <code>true</code> if mark() and reset() are supported,
     *         <code>false</code> otherwise. This implementation always
     *         returns <code>true</code>.
     */
    @Override
    public boolean markSupported() {
        return true;
    }

    /**
     * Reads a single character from this StringReader and returns the result as
     * an int. The 2 higher-order bytes are set to 0. If the end of reader was
     * encountered then return -1.
     *
     * @return the character read or -1 if end of reader.
     *
     * @exception java.io.IOException
     *                If the StringReader is already closed.
     */
    @Override
    public int read() throws IOException {
        synchronized (lock) {
            if (isOpen()) {
                if (pos != count) {
                    return str.charAt(pos++);
                }
                return -1;
            }
            throw new IOException("StringReader is closed");
        }
    }

    /**
     * Reads at most <code>count</code> characters from this StringReader and
     * stores them at <code>offset</code> in the character array
     * <code>buf</code>. Returns the number of characters actually read or -1
     * if the end of reader was encountered.
     *
     * @param buf
     *            character array to store the read characters
     * @param offset
     *            offset in buf to store the read characters
     * @param count
     *            maximum number of characters to read
     * @return the number of characters read or -1 if end of reader.
     *
     * @exception java.io.IOException
     *                If the StringReader is closed.
     */
    @Override
    public int read(char buf[], int offset, int count) throws IOException {
        // avoid int overflow
        if (0 <= offset && offset <= buf.length && 0 <= count
                && count <= buf.length - offset) {
            synchronized (lock) {
                if (isOpen()) {
                    if (pos == this.count) {
                        return -1;
                    }
                    int end = pos + count > this.count ? this.count : pos
                            + count;
                    str.getChars(pos, end, buf, offset);
                    int read = end - pos;
                    pos = end;
                    return read;
                }
                throw new IOException("StringReader is closed");
            }
        }
        throw new ArrayIndexOutOfBoundsException();
    }

    /**
     * Answers a <code>boolean</code> indicating whether or not this
     * StringReader is ready to be read without blocking. If the result is
     * <code>true</code>, the next <code>read()</code> will not block. If
     * the result is <code>false</code> this Reader may or may not block when
     * <code>read()</code> is sent. The implementation in StringReader always
     * returns <code>true</code> even when it has been closed.
     *
     * @return <code>true</code> if the receiver will not block when
     *         <code>read()</code> is called, <code>false</code> if unknown
     *         or blocking will occur.
     *
     * @exception java.io.IOException
     *                If an IO error occurs.
     */
    @Override
    public boolean ready() throws IOException {
        synchronized (lock) {
            if (isOpen()) {
                return true;
            }
            throw new IOException("StringReader is closed");
        }
    }

    /**
     * Reset this StringReader's position to the last <code>mark()</code>
     * location. Invocations of <code>read()/skip()</code> will occur from
     * this new location. If this Reader was not marked, the StringReader is
     * reset to the beginning of the String.
     *
     * @exception java.io.IOException
     *                If this StringReader has already been closed.
     */
    @Override
    public void reset() throws IOException {
        synchronized (lock) {
            if (isOpen()) {
                pos = markpos != -1 ? markpos : 0;
            } else {
                throw new IOException("StringReader is closed");
            }
        }
    }

    /**
     * Skips <code>count</code> number of characters in this StringReader.
     * Subsequent <code>read()</code>'s will not return these characters
     * unless <code>reset()</code> is used.
     *
     * @param count
     *            The number of characters to skip.
     * @return the number of characters actually skipped.
     *
     * @exception java.io.IOException
     *                If this StringReader has already been closed.
     */
    @Override
    public long skip(long count) throws IOException {
        synchronized (lock) {
            if (isOpen()) {
                if (count <= 0) {
                    return 0;
                }
                long skipped = 0;
                if (count < this.count - pos) {
                    pos = pos + (int) count;
                    skipped = count;
                } else {
                    skipped = this.count - pos;
                    pos = this.count;
                }
                return skipped;
            }
            throw new IOException("StringReader is closed");
        }
    }
}
