/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed 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 com.android.json.stream;

import java.io.Closeable;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

/**
 * Writes a JSON (<a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>) encoded value to a
 * stream, one token at a time. The stream includes both literal values (strings, numbers, booleans
 * and nulls) as well as the begin and end delimiters of objects and arrays.
 *
 * <h3>Encoding JSON</h3>
 *
 * To encode your data as JSON, create a new {@code JsonWriter}. Each JSON document must contain one
 * top-level array or object. Call methods on the writer as you walk the structure's contents,
 * nesting arrays and objects as necessary:
 *
 * <ul>
 *   <li>To write <strong>arrays</strong>, first call {@link #beginArray()}. Write each of the
 *       array's elements with the appropriate {@link #value} methods or by nesting other arrays and
 *       objects. Finally close the array using {@link #endArray()}.
 *   <li>To write <strong>objects</strong>, first call {@link #beginObject()}. Write each of the
 *       object's properties by alternating calls to {@link #name} with the property's value. Write
 *       property values with the appropriate {@link #value} method or by nesting other objects or
 *       arrays. Finally close the object using {@link #endObject()}.
 * </ul>
 *
 * <h3>Example</h3>
 *
 * Suppose we'd like to encode a stream of messages such as the following:
 *
 * <pre>{@code
 * [
 *   {
 *     "id": 912345678901,
 *     "text": "How do I write JSON on Android?",
 *     "geo": null,
 *     "user": {
 *       "name": "android_newb",
 *       "followers_count": 41
 *      }
 *   },
 *   {
 *     "id": 912345678902,
 *     "text": "@android_newb just use android.util.JsonWriter!",
 *     "geo": [50.454722, -104.606667],
 *     "user": {
 *       "name": "jesse",
 *       "followers_count": 2
 *     }
 *   }
 * ]
 * }</pre>
 *
 * This code encodes the above structure:
 *
 * <pre>{@code
 * public void writeJsonStream(OutputStream out, List<Message> messages) throws IOException {
 *   JsonWriter writer = new JsonWriter(new OutputStreamWriter(out, "UTF-8"));
 *   writer.setIndent("  ");
 *   writeMessagesArray(writer, messages);
 *   writer.close();
 * }
 *
 * public void writeMessagesArray(JsonWriter writer, List<Message> messages) throws IOException {
 *   writer.beginArray();
 *   for (Message message : messages) {
 *     writeMessage(writer, message);
 *   }
 *   writer.endArray();
 * }
 *
 * public void writeMessage(JsonWriter writer, Message message) throws IOException {
 *   writer.beginObject();
 *   writer.name("id").value(message.getId());
 *   writer.name("text").value(message.getText());
 *   if (message.getGeo() != null) {
 *     writer.name("geo");
 *     writeDoublesArray(writer, message.getGeo());
 *   } else {
 *     writer.name("geo").nullValue();
 *   }
 *   writer.name("user");
 *   writeUser(writer, message.getUser());
 *   writer.endObject();
 * }
 *
 * public void writeUser(JsonWriter writer, User user) throws IOException {
 *   writer.beginObject();
 *   writer.name("name").value(user.getName());
 *   writer.name("followers_count").value(user.getFollowersCount());
 *   writer.endObject();
 * }
 *
 * public void writeDoublesArray(JsonWriter writer, List<Double> doubles) throws IOException {
 *   writer.beginArray();
 *   for (Double value : doubles) {
 *     writer.value(value);
 *   }
 *   writer.endArray();
 * }
 * }</pre>
 *
 * <p>Each {@code JsonWriter} may be used to write a single JSON stream. Instances of this class are
 * not thread safe. Calls that would result in a malformed JSON string will fail with an {@link
 * IllegalStateException}.
 */
public class JsonWriter implements Closeable {

    /** The output data, containing at most one top-level array or object. */
    protected final Writer mOut;

    protected final List<JsonScope> mStack = new ArrayList<JsonScope>();

    {
        mStack.add(JsonScope.EMPTY_DOCUMENT);
    }

    /**
     * A string containing a full set of spaces for a single level of indentation, or null for no
     * pretty printing.
     */
    private String mIndent;

    /** The name/value separator; either ":" or ": ". */
    protected String mSeparator = ":";

    /**
     * Creates a new instance that writes a JSON-encoded stream to {@code out}.
     * For best performance, ensure {@link Writer} is buffered; wrapping in
     * {@link java.io.BufferedWriter BufferedWriter} if necessary.
     */
    public JsonWriter(Writer out) {
        if (out == null) {
            throw new NullPointerException("out == null");
        }
        this.mOut = out;
    }

    /**
     * Sets the indentation string to be repeated for each level of indentation
     * in the encoded document. If {@code indent.isEmpty()} the encoded document
     * will be compact. Otherwise the encoded document will be more
     * human-readable.
     *
     * @param indent a string containing only whitespace.
     */
    public void setIndent(String indent) {
        if (indent.isEmpty()) {
            this.mIndent = null;
            this.mSeparator = ":";
        } else {
            this.mIndent = indent;
            this.mSeparator = ": ";
        }
    }

    /**
     * Begins encoding a new array. Each call to this method must be paired with
     * a call to {@link #endArray}.
     *
     * @return this writer.
     */
    public JsonWriter beginArray() throws IOException {
        return open(JsonScope.EMPTY_ARRAY, "[");
    }

    /**
     * Ends encoding the current array.
     *
     * @return this writer.
     */
    public JsonWriter endArray() throws IOException {
        return close(JsonScope.EMPTY_ARRAY, JsonScope.NONEMPTY_ARRAY, "]");
    }

    /**
     * Begins encoding a new object. Each call to this method must be paired
     * with a call to {@link #endObject}.
     *
     * @return this writer.
     */
    public JsonWriter beginObject() throws IOException {
        return open(JsonScope.EMPTY_OBJECT, "{");
    }

    /**
     * Ends encoding the current object.
     *
     * @return this writer.
     */
    public JsonWriter endObject() throws IOException {
        return close(JsonScope.EMPTY_OBJECT, JsonScope.NONEMPTY_OBJECT, "}");
    }

    /**
     * Enters a new scope by appending any necessary whitespace and the given
     * bracket.
     */
    private JsonWriter open(JsonScope empty, String openBracket) throws IOException {
        beforeValue(true);
        mStack.add(empty);
        mOut.write(openBracket);
        return this;
    }

    /**
     * Closes the current scope by appending any necessary whitespace and the
     * given bracket.
     */
    private JsonWriter close(JsonScope empty, JsonScope nonempty, String closeBracket)
            throws IOException {
        JsonScope context = peek();
        if (context != nonempty && context != empty) {
            throw new IllegalStateException("Nesting problem: " + mStack);
        }

        mStack.remove(mStack.size() - 1);
        if (context == nonempty) {
            newline();
        }
        mOut.write(closeBracket);
        return this;
    }

    /** Returns the value on the top of the stack. */
    protected JsonScope peek() {
        return mStack.get(mStack.size() - 1);
    }

    /** Replace the value on the top of the stack with the given value. */
    protected void replaceTop(JsonScope topOfStack) {
        mStack.set(mStack.size() - 1, topOfStack);
    }

    /**
     * Encodes the property name.
     *
     * @param name the name of the forthcoming value. May not be null.
     * @return this writer.
     */
    public JsonWriter name(String name) throws IOException {
        if (name == null) {
            throw new NullPointerException("name == null");
        }
        beforeName();
        string(name);
        return this;
    }

    /**
     * Encodes {@code value}.
     *
     * @param value the literal string value, or null to encode a null literal.
     * @return this writer.
     */
    public JsonWriter value(String value) throws IOException {
        if (value == null) {
            return nullValue();
        }
        beforeValue(false);
        string(value);
        return this;
    }

    /**
     * Encodes {@code null}.
     *
     * @return this writer.
     */
    public JsonWriter nullValue() throws IOException {
        beforeValue(false);
        mOut.write("null");
        return this;
    }

    /**
     * Encodes {@code value}.
     *
     * @return this writer.
     */
    public JsonWriter value(boolean value) throws IOException {
        beforeValue(false);
        mOut.write(value ? "true" : "false");
        return this;
    }

    /**
     * Encodes {@code value}.
     *
     * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
     *     {@link Double#isInfinite() infinities}.
     * @return this writer.
     */
    public JsonWriter value(double value) throws IOException {
        if (Double.isNaN(value) || Double.isInfinite(value)) {
            throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
        }
        beforeValue(false);
        mOut.append(Double.toString(value));
        return this;
    }

    /**
     * Encodes {@code value}.
     *
     * @return this writer.
     */
    public JsonWriter value(long value) throws IOException {
        beforeValue(false);
        mOut.write(Long.toString(value));
        return this;
    }

    /**
     * Ensures all buffered data is written to the underlying {@link Writer}
     * and flushes that writer.
     */
    public void flush() throws IOException {
        mOut.flush();
    }

    /**
     * Flushes and closes this writer and the underlying {@link Writer}.
     *
     * @throws IOException if the JSON document is incomplete.
     */
    public void close() throws IOException {
        mOut.close();

        if (peek() != JsonScope.NONEMPTY_DOCUMENT) {
            throw new IOException("Incomplete document");
        }
    }

    private void string(String value) throws IOException {
        mOut.write("\"");
        for (int i = 0, length = value.length(); i < length; i++) {
            char c = value.charAt(i);

            /*
             * From RFC 4627, "All Unicode characters may be placed within the
             * quotation marks except for the characters that must be escaped:
             * quotation mark, reverse solidus, and the control characters
             * (U+0000 through U+001F)."
             */
            switch (c) {
                case '"':
                case '\\':
                case '/':
                    mOut.write('\\');
                    mOut.write(c);
                    break;

                case '\t':
                    mOut.write("\\t");
                    break;

                case '\b':
                    mOut.write("\\b");
                    break;

                case '\n':
                    mOut.write("\\n");
                    break;

                case '\r':
                    mOut.write("\\r");
                    break;

                case '\f':
                    mOut.write("\\f");
                    break;

                default:
                    if (c <= 0x1F) {
                        mOut.write(String.format("\\u%04x", (int) c));
                    } else {
                        mOut.write(c);
                    }
                    break;
            }

        }
        mOut.write("\"");
    }

    protected void newline() throws IOException {
        if (mIndent == null) {
            return;
        }

        mOut.write("\n");
        for (int i = 1; i < mStack.size(); i++) {
            mOut.write(mIndent);
        }
    }

    /**
     * Inserts any necessary separators and whitespace before a name. Also adjusts the stack to
     * expect the name's value.
     */
    protected void beforeName() throws IOException {
        JsonScope context = peek();
        if (context == JsonScope.NONEMPTY_OBJECT) { // first in object
            mOut.write(',');
        } else if (context != JsonScope.EMPTY_OBJECT) { // not in an object!
            throw new IllegalStateException("Nesting problem: " + mStack);
        }
        newline();
        replaceTop(JsonScope.DANGLING_NAME);
    }

    /**
     * Inserts any necessary separators and whitespace before a literal value, inline array, or
     * inline object. Also adjusts the stack to expect either a closing bracket or another element.
     *
     * @param root true if the value is a new array or object, the two values permitted as top-level
     *     elements.
     */
    protected void beforeValue(boolean root) throws IOException {
        switch (peek()) {
            case EMPTY_DOCUMENT: // first in document
                if (!root) {
                    throw new IllegalStateException(
                            "JSON must start with an array or an object.");
                }
                replaceTop(JsonScope.NONEMPTY_DOCUMENT);
                break;

            case EMPTY_ARRAY: // first in array
                replaceTop(JsonScope.NONEMPTY_ARRAY);
                newline();
                break;

            case NONEMPTY_ARRAY: // another in array
                mOut.append(',');
                newline();
                break;

            case DANGLING_NAME: // value for name
                mOut.append(mSeparator);
                replaceTop(JsonScope.NONEMPTY_OBJECT);
                break;

            case NONEMPTY_DOCUMENT:
                throw new IllegalStateException(
                        "JSON must have only one top-level value.");

            default:
                throw new IllegalStateException("Nesting problem: " + mStack);
        }
    }
}
