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 {
	/**
	 * The object used to synchronize operations on this stream. For efficiency, a character-stream
	 * object may use an object other than itself to protect critical sections. A subclass should
	 * therefore use the object in this field rather than <code>this</code> or a synchronized method.
	 */
	protected Object lock;

	/**
	 * 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();
	}
}