package java.io;

import ej.annotation.Nullable;

/**
 * Abstract class for writing to character streams. The only methods that a subclass must implement
 * are write(char[], int, int), flush(), and close(). Most subclasses, however, will override some
 * of the methods defined here in order to provide higher efficiency, additional functionality, or
 * both.
 *
 * @see OutputStreamWriter
 * @see Reader
 */
public abstract class Writer implements Appendable, Closeable, Flushable {

    /**
     * Creates a new character-stream writer whose critical sections will synchronize on the writer
     * itself.
     */
    protected Writer() {
        throw new RuntimeException();
    }

    /**
     * Creates a new character-stream writer whose critical sections will synchronize on the given
     * object.
     *
     * @param lock
     *        Object to synchronize on
     */
    protected Writer(Object lock) {
        throw new RuntimeException();
    }

    /**
     * Appends the specified character to this writer.
     *
     * <p>
     * An invocation of this method of the form <code>out.append(c)</code> behaves in exactly the same way
     * as the invocation
     *
     * <pre>
     * out.write(c)
     * </pre>
     *
     * @param c
     *        The 16-bit character to append
     *
     * @return This writer
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    @Override
    public Writer append(char c) throws IOException {
        throw new RuntimeException();
    }

    /**
     * Appends the specified character sequence to this writer.
     *
     * <p>
     * An invocation of this method of the form <code>out.append(csq)</code> behaves in exactly the same way
     * as the invocation
     *
     * <pre>
     * out.write(csq.toString())
     * </pre>
     *
     * <p>
     * Depending on the specification of <code>toString</code> for the character sequence <code>csq</code>, the
     * entire sequence may not be appended. For instance, invoking the <code>toString</code> method of a
     * character buffer will return a subsequence whose content depends upon the buffer's position and
     * limit.
     *
     * @param csq
     *        The character sequence to append. If <code>csq</code> is <code>null</code>, then the four
     *        characters <code>"null"</code> are appended to this writer.
     *
     * @return This writer
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    @Override
    public Writer append(@Nullable CharSequence csq) throws IOException {
        throw new RuntimeException();
    }

    /**
     * Appends a subsequence of the specified character sequence to this writer. <code>Appendable</code> .
     *
     * <p>
     * An invocation of this method of the form <code>out.append(csq, start,
     * end)</code> when <code>csq</code> is not <code>null</code> behaves in exactly the same way as the
     * invocation
     *
     * <pre>
     * out.write(csq.subSequence(start, end).toString())
     * </pre>
     *
     * @param csq
     *        The character sequence from which a subsequence will be appended. If <code>csq</code> is
     *        <code>null</code>, then characters will be appended as if <code>csq</code> contained the four
     *        characters <code>"null"</code>.
     *
     * @param start
     *        The index of the first character in the subsequence
     *
     * @param end
     *        The index of the character following the last character in the subsequence
     *
     * @return This writer
     *
     * @throws IndexOutOfBoundsException
     *         If <code>start</code> or <code>end</code> are negative, <code>start</code> is greater than
     *         <code>end</code>, or <code>end</code> is greater than <code>csq.length()</code>
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    @Override
    public Writer append(@Nullable CharSequence csq, int start, int end) throws IOException {
        throw new RuntimeException();
    }

    /**
     * Closes the stream, flushing it first. Once the stream has been closed, further write() or flush()
     * invocations will cause an IOException to be thrown. Closing a previously closed stream has no
     * effect.
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    @Override
    public abstract void close() throws IOException;

    /**
     * Flushes the stream. If the stream has saved any characters from the various write() methods in a
     * buffer, write them immediately to their intended destination. Then, if that destination is
     * another character or byte stream, flush it. Thus one flush() invocation will flush all the
     * buffers in a chain of Writers and OutputStreams.
     *
     * <p>
     * If the intended destination of this stream is an abstraction provided by the underlying operating
     * system, for example a file, then flushing the stream guarantees only that bytes previously
     * written to the stream are passed to the operating system for writing; it does not guarantee that
     * they are actually written to a physical device such as a disk drive.
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    @Override
    public abstract void flush() throws IOException;

    /**
     * Writes an array of characters.
     *
     * @param cbuf
     *        Array of characters to be written
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    public void write(char[] cbuf) throws IOException {
        throw new RuntimeException();
    }

    /**
     * Writes a portion of an array of characters.
     *
     * @param cbuf
     *        Array of characters
     *
     * @param off
     *        Offset from which to start writing characters
     *
     * @param len
     *        Number of characters to write
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    public abstract void write(char[] cbuf, int off, int len) throws IOException;

    /**
     * Writes a single character. The character to be written is contained in the 16 low-order bits of
     * the given integer value; the 16 high-order bits are ignored.
     *
     * <p>
     * Subclasses that intend to support efficient single-character output should override this method.
     *
     * @param c
     *        int specifying a character to be written
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    public void write(int c) throws IOException {
        throw new RuntimeException();
    }

    /**
     * Writes a string.
     *
     * @param str
     *        String to be written
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    public void write(String str) throws IOException {
        throw new RuntimeException();
    }

    /**
     * Writes a portion of a string.
     *
     * @param str
     *        A String
     *
     * @param off
     *        Offset from which to start writing characters
     *
     * @param len
     *        Number of characters to write
     *
     * @throws IndexOutOfBoundsException
     *         If <code>off</code> is negative, or <code>len</code> is negative, or <code>off+len</code> is negative
     *         or greater than the length of the given string
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    public void write(String str, int off, int len) throws IOException {
        throw new RuntimeException();
    }
}
