/*
 * Copyright 1999-2011 Alibaba Group.
 *  
 * 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.alibaba.dubbo.common.json;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;

import com.alibaba.dubbo.common.utils.Stack;

/**
 * JSON Writer.
 * 
 * w.objectBegin().objectItem("name").valueString("qianlei").objectEnd() = {name:"qianlei"}.
 * 
 * @author qian.lei
 */

public class JSONWriter
{
	private static final byte UNKNOWN = 0, ARRAY = 1, OBJECT = 2, OBJECT_VALUE = 3;

	private static class State
	{
		private byte type;
		private int itemCount = 0;

		State(byte t){ type = t; }
	}

	private Writer mWriter;

	private State mState = new State(UNKNOWN);

	private Stack<State> mStack = new Stack<State>();

	public JSONWriter(Writer writer)
	{
		mWriter = writer;
	}

	public JSONWriter(OutputStream is, String charset) throws UnsupportedEncodingException
	{
		mWriter = new OutputStreamWriter(is, charset);
	}

	/**
	 * object begin.
	 * 
	 * @return this.
	 * @throws IOException.
	 */
	public JSONWriter objectBegin() throws IOException
	{
		beforeValue();

		mWriter.write(JSON.LBRACE);
		mStack.push(mState);
		mState = new State(OBJECT);
		return this;
	}

	/**
	 * object end.
	 * 
	 * @return this.
	 * @throws IOException.
	 */
	public JSONWriter objectEnd() throws IOException
	{
		mWriter.write(JSON.RBRACE);
		mState = mStack.pop();
		return this;
	}

	/**
	 * object item.
	 * 
	 * @param name name.
	 * @return this.
	 * @throws IOException.
	 */
	public JSONWriter objectItem(String name) throws IOException
	{
		beforeObjectItem();

		mWriter.write(JSON.QUOTE);
		mWriter.write(escape(name));
		mWriter.write(JSON.QUOTE);
		mWriter.write(JSON.COLON);
		return this;
	}

	/**
	 * array begin.
	 * 
	 * @return this.
	 * @throws IOException.
	 */
	public JSONWriter arrayBegin() throws IOException
	{
		beforeValue();

		mWriter.write(JSON.LSQUARE);
		mStack.push(mState);
		mState = new State(ARRAY);
		return this;
	}

	/**
	 * array end, return array value.
	 * 
	 * @return this.
	 * @throws IOException.
	 */
	public JSONWriter arrayEnd() throws IOException
	{
		mWriter.write(JSON.RSQUARE);
		mState = mStack.pop();
		return this;
	}

	/**
	 * value.
	 * 
	 * @return this.
	 * @throws IOException.
	 */
	public JSONWriter valueNull() throws IOException
	{
		beforeValue();

		mWriter.write(JSON.NULL);
		return this;
	}

	/**
	 * value.
	 * 
	 * @param value value.
	 * @return this.
	 * @throws IOException
	 */
	public JSONWriter valueString(String value) throws IOException
	{
		beforeValue();

		mWriter.write(JSON.QUOTE);
		mWriter.write(escape(value));
		mWriter.write(JSON.QUOTE);
		return this;
	}

	/**
	 * value.
	 * 
	 * @param value value.
	 * @return this.
	 * @throws IOException
	 */
	public JSONWriter valueBoolean(boolean value) throws IOException
	{
		beforeValue();

		mWriter.write(value ? "true" : "false");
		return this;
	}

	/**
	 * value.
	 * 
	 * @param value value.
	 * @return this.
	 * @throws IOException
	 */
	public JSONWriter valueInt(int value) throws IOException
	{
		beforeValue();

		mWriter.write(String.valueOf(value));
		return this;
	}

	/**
	 * value.
	 * 
	 * @param value value.
	 * @return this.
	 * @throws IOException
	 */
	public JSONWriter valueLong(long value) throws IOException
	{
		beforeValue();

		mWriter.write(String.valueOf(value));
		return this;
	}

	/**
	 * value.
	 * 
	 * @param value value.
	 * @return this.
	 * @throws IOException
	 */
	public JSONWriter valueFloat(float value) throws IOException
	{
		beforeValue();

		mWriter.write(String.valueOf(value));
		return this;
	}

	/**
	 * value.
	 * 
	 * @param value value.
	 * @return this.
	 * @throws IOException
	 */
	public JSONWriter valueDouble(double value) throws IOException
	{
		beforeValue();

		mWriter.write(String.valueOf(value));
		return this;
	}

	private void beforeValue() throws IOException
	{
		switch( mState.type )
		{
			case ARRAY:
				if( mState.itemCount++ > 0 )
					mWriter.write(JSON.COMMA);
				return;
			case OBJECT:
				throw new IOException("Must call objectItem first.");
			case OBJECT_VALUE:
				mState.type = OBJECT;
				return;
		}
	}

	private void beforeObjectItem() throws IOException
	{
		switch( mState.type )
		{
			case OBJECT_VALUE:
				mWriter.write(JSON.NULL);
			case OBJECT:
				mState.type = OBJECT_VALUE;
				if( mState.itemCount++ > 0 )
					mWriter.write(JSON.COMMA);
				return;
			default:
				throw new IOException("Must call objectBegin first.");
		}
	}

	private static final String[] CONTROL_CHAR_MAP = new String[]{
		"\\u0000","\\u0001","\\u0002","\\u0003","\\u0004","\\u0005","\\u0006","\\u0007",
		"\\b","\\t","\\n","\\u000b","\\f","\\r","\\u000e","\\u000f",
		"\\u0010","\\u0011","\\u0012","\\u0013","\\u0014","\\u0015","\\u0016","\\u0017",
		"\\u0018","\\u0019","\\u001a","\\u001b","\\u001c","\\u001d","\\u001e","\\u001f"
	};

	private static String escape(String str)
	{
		if( str == null )
			return str;
		int len = str.length();
		if( len == 0 )
			return str;

        char c;
        StringBuilder sb = null;
        for(int i=0;i<len;i++)
        {
        	c = str.charAt(i);
        	if( c < ' ' ) // control char.
        	{
        		if( sb == null )
        		{
        			sb = new StringBuilder(len<<1);
					sb.append(str,0,i);
        		}
            	sb.append(CONTROL_CHAR_MAP[c]);
        	}
        	else
        	{
            	switch( c )
            	{
            		case '\\': case '/': case '"':
    	        		if( sb == null )
    	        		{
    	        			sb = new StringBuilder(len<<1);
    						sb.append(str,0,i);
    	        		}
            			sb.append('\\').append(c);
            			break;
            		default:
            			if( sb != null )
            				sb.append(c);
            	}
        	}
        }
        return sb == null ? str : sb.toString();
	}
}