/*
 *  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 java.io;

import java.security.AccessController;
import java.util.Formatter;
import java.util.IllegalFormatException;
import java.util.Locale;

import org.apache.harmony.luni.util.Msg;
import org.apache.harmony.luni.util.PriviAction;

/**
 * Wraps either an existing {@link OutputStream} or an existing {@link Writer}
 * and provides convenience methods for printing common data types in a human
 * readable format. No {@code IOException} is thrown by this class. Instead,
 * callers should use {@link #checkError()} to see if a problem has occurred in
 * this writer.
 */
public class PrintWriter extends Writer {
    /**
     * The writer to print data to.
     */
    protected Writer out;

    /**
     * Indicates whether this PrintWriter is in an error state.
     */
    private boolean ioError;

    /**
     * Indicates whether or not this PrintWriter should flush its contents after
     * printing a new line.
     */
    private boolean autoflush;

    private final String lineSeparator = AccessController
            .doPrivileged(new PriviAction<String>("line.separator")); //$NON-NLS-1$

    /**
     * Constructs a new {@code PrintWriter} with {@code out} as its target
     * stream. By default, the new print writer does not automatically flush its
     * contents to the target stream when a newline is encountered.
     *
     * @param out
     *            the target output stream.
     * @throws NullPointerException
     *             if {@code out} is {@code null}.
     */
    public PrintWriter(OutputStream out) {
        this(new OutputStreamWriter(out), false);
    }

    /**
     * Constructs a new {@code PrintWriter} with {@code out} as its target
     * stream. The parameter {@code autoflush} determines if the print writer
     * automatically flushes its contents to the target stream when a newline is
     * encountered.
     *
     * @param out
     *            the target output stream.
     * @param autoflush
     *            indicates whether contents are flushed upon encountering a
     *            newline sequence.
     * @throws NullPointerException
     *             if {@code out} is {@code null}.
     */
    public PrintWriter(OutputStream out, boolean autoflush) {
        this(new OutputStreamWriter(out), autoflush);
    }

    /**
     * Constructs a new {@code PrintWriter} with {@code wr} as its target
     * writer. By default, the new print writer does not automatically flush its
     * contents to the target writer when a newline is encountered.
     *
     * @param wr
     *            the target writer.
     * @throws NullPointerException
     *             if {@code wr} is {@code null}.
     */
    public PrintWriter(Writer wr) {
        this(wr, false);
    }

    /**
     * Constructs a new {@code PrintWriter} with {@code out} as its target
     * writer. The parameter {@code autoflush} determines if the print writer
     * automatically flushes its contents to the target writer when a newline is
     * encountered.
     *
     * @param wr
     *            the target writer.
     * @param autoflush
     *            indicates whether to flush contents upon encountering a
     *            newline sequence.
     * @throws NullPointerException
     *             if {@code out} is {@code null}.
     */
    public PrintWriter(Writer wr, boolean autoflush) {
        super(wr);
        this.autoflush = autoflush;
        out = wr;
    }

    /**
     * Constructs a new {@code PrintWriter} with {@code file} as its target. The
     * virtual machine's default character set is used for character encoding.
     * The print writer does not automatically flush its contents to the target
     * file when a newline is encountered. The output to the file is buffered.
     *
     * @param file
     *            the target file. If the file already exists, its contents are
     *            removed, otherwise a new file is created.
     * @throws FileNotFoundException
     *             if an error occurs while opening or creating the target file.
     * @throws SecurityException
     *             if a security manager exists and it denies writing to the
     *             target file.
     */
    public PrintWriter(File file) throws FileNotFoundException {
        // BEGIN android-modified
        this(new OutputStreamWriter(
                     new BufferedOutputStream(
                             new FileOutputStream(file), 8192)),
                false);
        // END android-modified
    }

    /**
     * Constructs a new {@code PrintWriter} with {@code file} as its target. The
     * character set named {@code csn} is used for character encoding.
     * The print writer does not automatically flush its contents to the target
     * file when a newline is encountered. The output to the file is buffered.
     *
     * @param file
     *            the target file. If the file already exists, its contents are
     *            removed, otherwise a new file is created.
     * @param csn
     *            the name of the character set used for character encoding.
     * @throws FileNotFoundException
     *             if an error occurs while opening or creating the target file.
     * @throws NullPointerException
     *             if {@code csn} is {@code null}.
     * @throws SecurityException
     *             if a security manager exists and it denies writing to the
     *             target file.
     * @throws UnsupportedEncodingException
     *             if the encoding specified by {@code csn} is not supported.
     */
    public PrintWriter(File file, String csn) throws FileNotFoundException,
            UnsupportedEncodingException {
        // BEGIN android-modified
        this(new OutputStreamWriter(
                     new BufferedOutputStream(
                             new FileOutputStream(file), 8192), csn),
                false);
        // END android-modified
    }

    /**
     * Constructs a new {@code PrintWriter} with the file identified by {@code
     * fileName} as its target. The virtual machine's default character set is
     * used for character encoding. The print writer does not automatically
     * flush its contents to the target file when a newline is encountered. The
     * output to the file is buffered.
     *
     * @param fileName
     *            the target file's name. If the file already exists, its
     *            contents are removed, otherwise a new file is created.
     * @throws FileNotFoundException
     *             if an error occurs while opening or creating the target file.
     * @throws SecurityException
     *             if a security manager exists and it denies writing to the
     *             target file.
     */
    public PrintWriter(String fileName) throws FileNotFoundException {
        // BEGIN android-modified
        this(new OutputStreamWriter(
                     new BufferedOutputStream(
                             new FileOutputStream(fileName), 8192)),
                false);
        // END android-modified
    }

     /**
     * Constructs a new {@code PrintWriter} with the file identified by {@code
     * fileName} as its target. The character set named {@code csn} is used for
     * character encoding. The print writer does not automatically flush its
     * contents to the target file when a newline is encountered. The output to
     * the file is buffered.
     *
     * @param fileName
     *            the target file's name. If the file already exists, its
     *            contents are removed, otherwise a new file is created.
     * @param csn
     *            the name of the character set used for character encoding.
     * @throws FileNotFoundException
     *             if an error occurs while opening or creating the target file.
     * @throws NullPointerException
     *             if {@code csn} is {@code null}.
     * @throws SecurityException
     *             if a security manager exists and it denies writing to the
     *             target file.
     * @throws UnsupportedEncodingException
     *             if the encoding specified by {@code csn} is not supported.
     */
    public PrintWriter(String fileName, String csn)
            throws FileNotFoundException, UnsupportedEncodingException {
        // BEGIN android-modified
        this(new OutputStreamWriter(
                     new BufferedOutputStream(
                             new FileOutputStream(fileName), 8192), csn),
                false);
        // END android-modified
    }

    /**
     * Flushes this writer and returns the value of the error flag.
     *
     * @return {@code true} if either an {@code IOException} has been thrown
     *         previously or if {@code setError()} has been called;
     *         {@code false} otherwise.
     * @see #setError()
     */
    public boolean checkError() {
        Writer delegate = out;
        if (delegate == null) {
            return ioError;
        }

        flush();
        return ioError || delegate.checkError();
    }

    /**
     * Sets the error state of the stream to false.
     * @since 1.6
     * @hide
     */
    protected void clearError() {
        synchronized (lock) {
            ioError = false;
        }
    }

    /**
     * Closes this print writer. Flushes this writer and then closes the target.
     * If an I/O error occurs, this writer's error flag is set to {@code true}.
     */
    @Override
    public void close() {
        synchronized (lock) {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    setError();
                }
                out = null;
            }
        }
    }

    /**
     * Ensures that all pending data is sent out to the target. It also
     * flushes the target. If an I/O error occurs, this writer's error
     * state is set to {@code true}.
     */
    @Override
    public void flush() {
        synchronized (lock) {
            if (out != null) {
                try {
                    out.flush();
                } catch (IOException e) {
                    setError();
                }
            } else {
                setError();
            }
        }
    }

    /**
     * Writes a string formatted by an intermediate {@code Formatter} to the
     * target using the specified format string and arguments. For the locale,
     * the default value of the current virtual machine instance is used. If
     * automatic flushing is enabled then the buffer is flushed as well.
     *
     * @param format
     *            the format string used for {@link java.util.Formatter#format}.
     * @param args
     *            the list of arguments passed to the formatter. If there are
     *            more arguments than required by the {@code format} string,
     *            then the additional arguments are ignored.
     * @return this writer.
     * @throws IllegalFormatException
     *             if the format string is illegal or incompatible with the
     *             arguments, if there are not enough arguments or if any other
     *             error regarding the format string or arguments is detected.
     * @throws NullPointerException
     *             if {@code format} is {@code null}.
     */
    public PrintWriter format(String format, Object... args) {
        return format(Locale.getDefault(), format, args);
    }

    /**
     * Writes a string formatted by an intermediate {@code Formatter} to the
     * target using the specified locale, format string and arguments. If
     * automatic flushing is enabled then this writer is flushed.
     *
     * @param l
     *            the locale used in the method. No localization will be applied
     *            if {@code l} is {@code null}.
     * @param format
     *            the format string used for {@link java.util.Formatter#format}.
     * @param args
     *            the list of arguments passed to the formatter. If there are
     *            more arguments than required by the {@code format} string,
     *            then the additional arguments are ignored.
     * @return this writer.
     * @throws IllegalFormatException
     *             if the format string is illegal or incompatible with the
     *             arguments, if there are not enough arguments or if any other
     *             error regarding the format string or arguments is detected.
     * @throws NullPointerException
     *             if {@code format} is {@code null}.
     */
    public PrintWriter format(Locale l, String format, Object... args) {
        if (format == null) {
            throw new NullPointerException(Msg.getString("K0351")); //$NON-NLS-1$
        }
        new Formatter(this, l).format(format, args);
        if (autoflush) {
            flush();
        }
        return this;
    }

    /**
     * Prints a formatted string. The behavior of this method is the same as
     * this writer's {@code #format(String, Object...)} method. For the locale,
     * the default value of the current virtual machine instance is used.
     *
     * @param format
     *            the format string used for {@link java.util.Formatter#format}.
     * @param args
     *            the list of arguments passed to the formatter. If there are
     *            more arguments than required by the {@code format} string,
     *            then the additional arguments are ignored.
     * @return this writer.
     * @throws IllegalFormatException
     *             if the format string is illegal or incompatible with the
     *             arguments, if there are not enough arguments or if any other
     *             error regarding the format string or arguments is detected.
     * @throws NullPointerException
     *             if {@code format} is {@code null}.
     */
    public PrintWriter printf(String format, Object... args) {
        return format(format, args);
    }

    /**
     * Prints a formatted string. The behavior of this method is the same as
     * this writer's {@code #format(Locale, String, Object...)} method.
     *
     * @param l
     *            the locale used in the method. No localization will be applied
     *            if {@code l} is {@code null}.
     * @param format
     *            the format string used for {@link java.util.Formatter#format}.
     * @param args
     *            the list of arguments passed to the formatter. If there are
     *            more arguments than required by the {@code format} string,
     *            then the additional arguments are ignored.
     * @return this writer.
     * @throws IllegalFormatException
     *             if the format string is illegal or incompatible with the
     *             arguments, if there are not enough arguments or if any other
     *             error regarding the format string or arguments is detected.
     * @throws NullPointerException
     *             if {@code format} is {@code null}.
     */
    public PrintWriter printf(Locale l, String format, Object... args) {
        return format(l, format, args);
    }

    /**
     * Prints the string representation of the specified character array
     * to the target.
     *
     * @param charArray
     *            the character array to print to the target.
     * @see #print(String)
     */
    public void print(char[] charArray) {
        print(new String(charArray, 0, charArray.length));
    }

    /**
     * Prints the string representation of the specified character to the
     * target.
     *
     * @param ch
     *            the character to print to the target.
     * @see #print(String)
     */
    public void print(char ch) {
        print(String.valueOf(ch));
    }

    /**
     * Prints the string representation of the specified double to the target.
     *
     * @param dnum
     *            the double value to print to the target.
     * @see #print(String)
     */
    public void print(double dnum) {
        print(String.valueOf(dnum));
    }

    /**
     * Prints the string representation of the specified float to the target.
     *
     * @param fnum
     *            the float value to print to the target.
     * @see #print(String)
     */
    public void print(float fnum) {
        print(String.valueOf(fnum));
    }

    /**
     * Prints the string representation of the specified integer to the target.
     *
     * @param inum
     *            the integer value to print to the target.
     * @see #print(String)
     */
    public void print(int inum) {
        print(String.valueOf(inum));
    }

    /**
     * Prints the string representation of the specified long to the target.
     *
     * @param lnum
     *            the long value to print to the target.
     * @see #print(String)
     */
    public void print(long lnum) {
        print(String.valueOf(lnum));
    }

    /**
     * Prints the string representation of the specified object to the target.
     *
     * @param obj
     *            the object to print to the target.
     * @see #print(String)
     */
    public void print(Object obj) {
        print(String.valueOf(obj));
    }

    /**
     * Prints a string to the target. The string is converted to an array of
     * bytes using the encoding chosen during the construction of this writer.
     * The bytes are then written to the target with {@code write(int)}.
     * <p>
     * If an I/O error occurs, this writer's error flag is set to {@code true}.
     *
     * @param str
     *            the string to print to the target.
     * @see #write(int)
     */
    public void print(String str) {
        write(str != null ? str : String.valueOf((Object) null));
    }

    /**
     * Prints the string representation of the specified boolean to the target.
     *
     * @param bool
     *            the boolean value to print the target.
     * @see #print(String)
     */
    public void print(boolean bool) {
        print(String.valueOf(bool));
    }

    /**
     * Prints the string representation of the system property {@code
     * "line.separator"} to the target. Flushes this writer if the autoflush
     * flag is set to {@code true}.
     */
    public void println() {
        synchronized (lock) {
            print(lineSeparator);
            if (autoflush) {
                flush();
            }
        }
    }

    /**
     * Prints the string representation of the specified character array
     * followed by the system property {@code "line.separator"} to the target.
     * Flushes this writer if the autoflush flag is set to {@code true}.
     *
     * @param charArray
     *            the character array to print to the target.
     * @see #print(String)
     */
    public void println(char[] charArray) {
        println(new String(charArray, 0, charArray.length));
    }

    /**
     * Prints the string representation of the specified character followed by
     * the system property {@code "line.separator"} to the target. Flushes this
     * writer if the autoflush flag is set to {@code true}.
     *
     * @param ch
     *            the character to print to the target.
     * @see #print(String)
     */
    public void println(char ch) {
        println(String.valueOf(ch));
    }

    /**
     * Prints the string representation of the specified double followed by the
     * system property {@code "line.separator"} to the target. Flushes this
     * writer if the autoflush flag is set to {@code true}.
     *
     * @param dnum
     *            the double value to print to the target.
     * @see #print(String)
     */
    public void println(double dnum) {
        println(String.valueOf(dnum));
    }

    /**
     * Prints the string representation of the specified float followed by the
     * system property {@code "line.separator"} to the target. Flushes this
     * writer if the autoflush flag is set to {@code true}.
     *
     * @param fnum
     *            the float value to print to the target.
     * @see #print(String)
     */
    public void println(float fnum) {
        println(String.valueOf(fnum));
    }

    /**
     * Prints the string representation of the specified integer followed by the
     * system property {@code "line.separator"} to the target. Flushes this
     * writer if the autoflush flag is set to {@code true}.
     *
     * @param inum
     *            the integer value to print to the target.
     * @see #print(String)
     */
    public void println(int inum) {
        println(String.valueOf(inum));
    }

    /**
     * Prints the string representation of the specified long followed by the
     * system property {@code "line.separator"} to the target. Flushes this
     * writer if the autoflush flag is set to {@code true}.
     *
     * @param lnum
     *            the long value to print to the target.
     * @see #print(String)
     */
    public void println(long lnum) {
        println(String.valueOf(lnum));
    }

    /**
     * Prints the string representation of the specified object followed by the
     * system property {@code "line.separator"} to the target. Flushes this
     * writer if the autoflush flag is set to {@code true}.
     *
     * @param obj
     *            the object to print to the target.
     * @see #print(String)
     */
    public void println(Object obj) {
        println(String.valueOf(obj));
    }

    /**
     * Prints a string followed by the system property {@code "line.separator"}
     * to the target. The string is converted to an array of bytes using the
     * encoding chosen during the construction of this writer. The bytes are
     * then written to the target with {@code write(int)}. Finally, this writer
     * is flushed if the autoflush flag is set to {@code true}.
     * <p>
     * If an I/O error occurs, this writer's error flag is set to {@code true}.
     *
     * @param str
     *            the string to print to the target.
     * @see #write(int)
     */
    public void println(String str) {
        synchronized (lock) {
            print(str);
            println();
        }
    }

    /**
     * Prints the string representation of the specified boolean followed by the
     * system property {@code "line.separator"} to the target. Flushes this
     * writer if the autoflush flag is set to {@code true}.
     *
     * @param bool
     *            the boolean value to print to the target.
     * @see #print(String)
     */
    public void println(boolean bool) {
        println(String.valueOf(bool));
    }

    /**
     * Sets the error flag of this writer to true.
     */
    protected void setError() {
        synchronized (lock) {
            ioError = true;
        }
    }

    /**
     * Writes the character buffer {@code buf} to the target.
     *
     * @param buf
     *            the non-null array containing characters to write.
     */
    @Override
    public void write(char[] buf) {
        // BEGIN android-note
        // changed array notation to be consistent with the rest of harmony
        // END android-note
        write(buf, 0, buf.length);
    }

    /**
     * Writes {@code count} characters from {@code buffer} starting at {@code
     * offset} to the target.
     * <p>
     * This writer's error flag is set to {@code true} if this writer is closed
     * or an I/O error occurs.
     *
     * @param buf
     *            the buffer to write to the target.
     * @param offset
     *            the index of the first character in {@code buffer} to write.
     * @param count
     *            the number of characters in {@code buffer} to write.
     * @throws IndexOutOfBoundsException
     *             if {@code offset < 0} or {@code count < 0}, or if {@code
     *             offset + count} is greater than the length of {@code buf}.
     */
    @Override
    public void write(char[] buf, int offset, int count) {
        // BEGIN android-note
        // changed array notation to be consistent with the rest of harmony
        // END android-note
        doWrite(buf, offset, count);
    }

    /**
     * Writes one character to the target. Only the two least significant bytes
     * of the integer {@code oneChar} are written.
     * <p>
     * This writer's error flag is set to {@code true} if this writer is closed
     * or an I/O error occurs.
     *
     * @param oneChar
     *            the character to write to the target.
     */
    @Override
    public void write(int oneChar) {
        doWrite(new char[] { (char) oneChar }, 0, 1);
    }

    private final void doWrite(char[] buf, int offset, int count) {
        // BEGIN android-note
        // changed array notation to be consistent with the rest of harmony
        // END android-note
        synchronized (lock) {
            if (out != null) {
                try {
                    out.write(buf, offset, count);
                } catch (IOException e) {
                    setError();
                }
            } else {
                setError();
            }
        }
    }

    /**
     * Writes the characters from the specified string to the target.
     *
     * @param str
     *            the non-null string containing the characters to write.
     */
    @Override
    public void write(String str) {
        write(str.toCharArray());
    }

    /**
     * Writes {@code count} characters from {@code str} starting at {@code
     * offset} to the target.
     *
     * @param str
     *            the non-null string containing the characters to write.
     * @param offset
     *            the index of the first character in {@code str} to write.
     * @param count
     *            the number of characters from {@code str} to write.
     * @throws IndexOutOfBoundsException
     *             if {@code offset < 0} or {@code count < 0}, or if {@code
     *             offset + count} is greater than the length of {@code str}.
     */
    @Override
    public void write(String str, int offset, int count) {
        write(str.substring(offset, offset + count).toCharArray());
    }

    /**
     * Appends the character {@code c} to the target.
     *
     * @param c
     *            the character to append to the target.
     * @return this writer.
     */
    @Override
    public PrintWriter append(char c) {
        write(c);
        return this;
    }

    /**
     * Appends the character sequence {@code csq} to the target. This
     * method works the same way as {@code PrintWriter.print(csq.toString())}.
     * If {@code csq} is {@code null}, then the string "null" is written
     * to the target.
     *
     * @param csq
     *            the character sequence appended to the target.
     * @return this writer.
     */
    @Override
    public PrintWriter append(CharSequence csq) {
        if (null == csq) {
            append(TOKEN_NULL, 0, TOKEN_NULL.length());
        } else {
            append(csq, 0, csq.length());
        }
        return this;
    }

    /**
     * Appends a subsequence of the character sequence {@code csq} to the
     * target. This method works the same way as {@code
     * PrintWriter.print(csq.subsequence(start, end).toString())}. If {@code
     * csq} is {@code null}, then the specified subsequence of the string "null"
     * will be written to the target.
     *
     * @param csq
     *            the character sequence appended to the target.
     * @param start
     *            the index of the first char in the character sequence appended
     *            to the target.
     * @param end
     *            the index of the character following the last character of the
     *            subsequence appended to the target.
     * @return this writer.
     * @throws StringIndexOutOfBoundsException
     *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
     *             either {@code start} or {@code end} are greater or equal than
     *             the length of {@code csq}.
     */
    @Override
    public PrintWriter append(CharSequence csq, int start, int end) {
        if (null == csq) {
            csq = TOKEN_NULL;
        }
        String output = csq.subSequence(start, end).toString();
        write(output, 0, output.length());
        return this;
    }
}
