/*******************************************************************************
 * Copyright (c) 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.jsdt.debug.internal.jsd2.transport;

import java.math.BigDecimal;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.wst.jsdt.debug.internal.jsd2.Tracing;
import org.eclipse.wst.jsdt.debug.internal.jsd2.jsdi.NullValueImpl;
import org.eclipse.wst.jsdt.debug.internal.jsd2.jsdi.UndefinedValueImpl;

/**
 * Class for reading / writing JSON objects
 * <br><br>
 * Crossfire has the following types:
 * <ul>
 * 	<li>object</li>
 * 	<li>function</li>
 * 	<li>boolean</li>
 * 	<li>number</li>
 * 	<li>string</li>
 * 	<li>undefined</li>
 * 	<li>ref</li>
 * </ul> 
 * @since 1.0
 */
public final class JSON {

	static boolean TRACE = false;
	
	/**
	 * Standard line feed / control feed terminus for Crossfire packets
	 */
	public static final String LINE_FEED = "\r\n"; //$NON-NLS-1$
	/**
	 * The default <code>Content-Length:</code> preamble
	 */
	public static final String CONTENT_LENGTH = "Content-Length:"; //$NON-NLS-1$
	/**
	 * Enables / Disables tracing in the all of the JSDI implementations
	 * 
	 * @param trace
	 */
	public static void setTracing(boolean trace) {
		TRACE = trace;
	}
	
	/**
	 * Constructor
	 * 
	 * No instantiation
	 */
	private JSON() {}
	
	/**
	 * Writes the given key / value pair to the buffer in the form: <code>"key":["]value["]</code>
	 * 
	 * @param key
	 * @param value
	 * @param buffer
	 */
	public static void writeKeyValue(String key, Object value, StringBuffer buffer) {
		writeString(key, buffer);
		buffer.append(':');
		writeValue(value, buffer);
	}
	
	/**
	 * Writes out the given value to the buffer. <br><br>
	 * Values are written out as:
	 * <ul>
	 * 	<li>Boolean / Number: <code>value.toString()</code></li>
	 * 	<li>String: <code>"value"</code></li>
	 * 	<li>null: <code>null</code>
	 * 	<li>Collection: <code>[{@link #writeValue(Object, StringBuffer)},...]</code></li>
	 * 	<li>Map: <code>{"key":{@link #writeValue(Object, StringBuffer)},...}</code></li>
	 * </ul>
	 * 
	 * @param value
	 * @param buffer
	 */
	public static void writeValue(Object value, StringBuffer buffer) {
		if (value == null) {
			buffer.append(NullValueImpl.NULL);
		}
		else if (value instanceof Boolean || value instanceof Number) {
			buffer.append(value.toString());
		}
		else if (value instanceof String) {
			writeString((String) value, buffer);
		}
		else if(value instanceof Collection) {
			writeArray((Collection) value, buffer);
		}
		else if(value instanceof Map) {
			writeObject((Map) value, buffer);
		}
	}
	
	/**
	 * Writes the given {@link String} into the given {@link StringBuffer} properly escaping
	 * all control characters
	 * 
	 * @param string
	 * @param buffer
	 */
	public static void writeString(String string, StringBuffer buffer) {
		buffer.append('"');
		int length = string.length();
		for (int i = 0; i < length; i++) {
			char c = string.charAt(i);
			switch (c) {
				case '"' :
				case '\\' :
				case '/' : {
					buffer.append('\\');
					buffer.append(c);
					break;
				}
				case '\b' : {
					buffer.append("\\b"); //$NON-NLS-1$
					break;
				}
				case '\f' : {
					buffer.append("\\f"); //$NON-NLS-1$
					break;
				}
				case '\n' : {
					buffer.append("\\n"); //$NON-NLS-1$
					break;
				}
				case '\r' : {
					buffer.append("\\r"); //$NON-NLS-1$
					break;
				}
				case '\t' : {
					buffer.append("\\t"); //$NON-NLS-1$
					break;
				}
				default :
					if (Character.isISOControl(c)) {
						buffer.append("\\u"); //$NON-NLS-1$
						String hexString = Integer.toHexString(c);
						for (int j = hexString.length(); j < 4; j++) {
							buffer.append('0');
						}
						buffer.append(hexString);
					} else {
						buffer.append(c);
					}
			}
		}
		buffer.append('"');
	}

	/**
	 * Writes the given collection into an array string of the form: <code>[{@link #writeValue(Object, StringBuffer)},...]</code>
	 * 
	 * @param collection
	 * @param buffer
	 */
	static void writeArray(Collection collection, StringBuffer buffer) {
		buffer.append('[');
		for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
			writeValue(iterator.next(), buffer);
			if(iterator.hasNext()) {
				buffer.append(',');
			}
		}
		buffer.append(']');
	}
	
	/**
	 * Writes an object mapping to the given buffer in the form: <code>{"key":{@link #writeValue(Object, StringBuffer)},...}</code>
	 * 
	 * @param map
	 * @param buffer
	 */
	public static void writeObject(Map map, StringBuffer buffer) {
		buffer.append('{');
		for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) {
			String key = (String) iterator.next();
			writeString(key, buffer);
			buffer.append(':');
			writeValue(map.get(key), buffer);
			if(iterator.hasNext()) {
				buffer.append(',');
			}
		}
		buffer.append('}');
	}
	
	/**
	 * Writes the <code>Content-Length:N</code> preamble to the head of the given buffer
	 * 
	 * @param buffer
	 * @param length
	 */
	public static void writeContentLength(StringBuffer buffer, int length) {
		StringBuffer buff = new StringBuffer(18);
		buff.append(CONTENT_LENGTH).append(length).append(LINE_FEED).append(LINE_FEED);
		buffer.insert(0, buff.toString());
	}
	
	/**
	 * Serializes the given {@link PacketImpl} to a {@link String}
	 * 
	 * @param packet the packet to serialize
	 * 
	 * @return the serialized {@link String}, never <code>null</code>
	 */
	public static String serialize(PacketImpl packet) {
		Object json = packet.toJSON();
		StringBuffer buffer = new StringBuffer();
		writeValue(json, buffer);
		int length = buffer.length();
		writeContentLength(buffer, length);
		buffer.append(LINE_FEED);
		if(TRACE) {
			Tracing.writeString("SERIALIZE: " + packet.getType() +" packet as "+buffer.toString()); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return buffer.toString();
	}
	
	/**
	 * Reads and returns a new object from the given JSON {@link String}. This method
	 * will throw an {@link IllegalStateException} if parsing fails.
	 * 
	 * @param jsonString
	 * @return the object, never <code>null</code>
	 */
	public static Object read(String jsonString) {
		return parse(new StringCharacterIterator(jsonString));
	}
	
	/**
	 * Reads and returns a new object form the given {@link CharacterIterator} that corresponds to
	 * a properly formatted JSON string. This method will throw an {@link IllegalStateException} if
	 * parsing fails.
	 * 
	 * @param it the {@link CharacterIterator} to parse
	 * @return the object, never <code>null</code>
	 */
	public static Object parse(CharacterIterator it) {
		parseWhitespace(it);
		Object result = parseValue(it);
		parseWhitespace(it);
		if (it.current() != CharacterIterator.DONE) {
			throw error("should be done", it); //$NON-NLS-1$
		}
		return result;
	}
	
	/**
	 * Creates an {@link IllegalStateException} for the given message and iterator
	 * 
	 * @param message the message for the exception
	 * @param it the {@link CharacterIterator} to parse
	 * 
	 * @return a new {@link IllegalStateException} 
	 */
	private static RuntimeException error(String message, CharacterIterator it) {
		return new IllegalStateException("[" + it.getIndex() + "] " + message); //$NON-NLS-1$//$NON-NLS-2$
	}
	
	/**
	 * Chews up whitespace from the iterator
	 * 
	 * @param it the {@link CharacterIterator} to parse
	 */
	private static void parseWhitespace(CharacterIterator it) {
		char c = it.current();
		while (Character.isWhitespace(c)) {
			c = it.next();
		}
	}
	
	/**
	 * Parses the {@link Object} from the {@link CharacterIterator}. This method 
	 * delegates to the proper parsing method depending on the current iterator context.
	 * This method will throw an {@link IllegalStateException} if parsing fails.
	 * 
	 * @param it the {@link CharacterIterator} to parse
	 * 
	 * @return the new object, never <code>null</code>
	 * @see #parseString(CharacterIterator)
	 * @see #parseNumber(CharacterIterator)
	 * @see #parseArray(CharacterIterator)
	 * @see #parseObject(CharacterIterator)
	 */
	private static Object parseValue(CharacterIterator it) {
		switch (it.current()) {
			case '{' : {
				return parseObject(it);
			}
			case '[' : {
				return parseArray(it);
			}
			case '"' : {
				return parseString(it);
			}
			case '-' :
			case '0' :
			case '1' :
			case '2' :
			case '3' :
			case '4' :
			case '5' :
			case '6' :
			case '7' :
			case '8' :
			case '9' : {
				return parseNumber(it);
			}
			case 't' : {
				parseText(Boolean.TRUE.toString(), it);
				return Boolean.TRUE;
			}
			case 'f' : {
				parseText(Boolean.FALSE.toString(), it);
				return Boolean.FALSE;
			}
			case 'n' : {
				parseText(NullValueImpl.NULL, it);
				return null;
			}
			case 'u': {
				parseText(UndefinedValueImpl.UNDEFINED, it);
				return null;
			}
		}
		throw error("Bad JSON starting character '" + it.current() + "'", it); //$NON-NLS-1$ //$NON-NLS-2$;
	}
	
	/**
	 * Parses the JSON string from the {@link CharacterIterator}
	 * 
	 * @param it the {@link CharacterIterator} to parse
	 * @return the JSON {@link String}, never <code>null</code>
	 */
	private static String parseString(CharacterIterator it) {
		char c = it.next();
		if (c == '"') {
			it.next();
			return ""; //$NON-NLS-1$
		}
		StringBuffer buffer = new StringBuffer();
		while (c != CharacterIterator.DONE && c != '"') {
			if (Character.isISOControl(c)) {
				//ignore it and continue
				c = it.next();
				continue;
				//throw error("illegal ISO control character: '" + Integer.toHexString(c) + "'", it); //$NON-NLS-1$ //$NON-NLS-2$);
			}
			if (c == '\\') {
				c = it.next();
				switch (c) {
					case '"' :
					case '\\' :
					case '/' : {
						buffer.append(c);
						break;
					}
					case 'b' : {
						buffer.append('\b');
						break;
					}
					case 'f' : {
						buffer.append('\f');
						break;
					}
					case 'n' : {
						buffer.append('\n');
						break;
					}
					case 'r' : {
						buffer.append('\r');
						break;
					}
					case 't' : {
						buffer.append('\t');
						break;
					}
					case 'u' : {
						StringBuffer unicode = new StringBuffer(4);
						for (int i = 0; i < 4; i++) {
							unicode.append(it.next());
						}
						try {
							buffer.append((char) Integer.parseInt(unicode.toString(), 16));
						} catch (NumberFormatException e) {
							throw error("expected a unicode hex number but was '" + unicode.toString() + "'", it); //$NON-NLS-1$ //$NON-NLS-2$););
						}
						break;
					}
					default : {
						throw error("illegal escape character '" + c + "'", it); //$NON-NLS-1$ //$NON-NLS-2$););
					}
				}
			} else {
				buffer.append(c);
			}
			c = it.next();
		}
		c = it.next();
		return buffer.toString();
	}
	
	/**
	 * Parses an {@link Map} object from the iterator or throws an
	 * {@link IllegalStateException} if parsing fails.
	 * 
	 * @param it the {@link CharacterIterator} to parse
	 * @return a new {@link Map} object, never <code>null</code>
	 */
	private static Map parseObject(CharacterIterator it) {
		it.next();
		parseWhitespace(it);
		if (it.current() == '}') {
			it.next();
			return Collections.EMPTY_MAP;
		}

		Map map = new HashMap();
		while (it.current() != CharacterIterator.DONE) {
			if (it.current() != '"') {
				throw error("expected a string start '\"' but was '" + it.current() + "'", it); //$NON-NLS-1$ //$NON-NLS-2$
			}
			String key = parseString(it);
			if (map.containsKey(key)) {
				throw error("' already defined" + "key '" + key, it); //$NON-NLS-1$ //$NON-NLS-2$
			}
			parseWhitespace(it);
			if (it.current() != ':') {
				throw error("expected a pair separator ':' but was '" + it.current() + "'", it); //$NON-NLS-1$ //$NON-NLS-2$
			}
			it.next();
			parseWhitespace(it);
			Object value = parseValue(it);
			map.put(key, value);
			parseWhitespace(it);
			if (it.current() == ',') {
				it.next();
				parseWhitespace(it);
				continue;
			}
			if (it.current() != '}') {
				throw error("expected an object close '}' but was '" + it.current() + "'", it); //$NON-NLS-1$ //$NON-NLS-2$
			}
			break;
		}
		it.next();
		return map;
	}
	
	/**
	 * Parses an {@link ArrayList} from the given iterator or throws an
	 * {@link IllegalStateException} if parsing fails
	 * 
	 * @param it the {@link CharacterIterator} to parse
	 * @return a new {@link ArrayList} object never <code>null</code>
	 */
	private static List parseArray(CharacterIterator it) {
		it.next();
		parseWhitespace(it);
		if (it.current() == ']') {
			it.next();
			return Collections.EMPTY_LIST;
		}

		List list = new ArrayList();
		while (it.current() != CharacterIterator.DONE) {
			Object value = parseValue(it);
			list.add(value);
			parseWhitespace(it);
			if (it.current() == ',') {
				it.next();
				parseWhitespace(it);
				continue;
			}
			if (it.current() != ']') {
				throw error("expected an array close ']' but was '" + it.current() + "'", it); //$NON-NLS-1$ //$NON-NLS-2$
			}
			break;
		}
		it.next();
		return list;
	}

	/**
	 * @param string
	 * @param it
	 */
	private static void parseText(String string, CharacterIterator it) {
		int length = string.length();
		char c = it.current();
		for (int i = 0; i < length; i++) {
			if (c != string.charAt(i)) {
				throw error("expected to parse '" + string + "' but character " + (i + 1) + " was '" + c + "'", it); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$;
			}
			c = it.next();
		}
	}

	/**
	 * Parses a {@link Number} object from the given {@link CharacterIterator}
	 * 
	 * @param it
	 * @return a new {@link Number}, never <code>null</code>
	 */
	private static Object parseNumber(CharacterIterator it) {
		StringBuffer buffer = new StringBuffer();
		char c = it.current();
		while (Character.isDigit(c) || c == '-' || c == '+' || c == '.' || c == 'e' || c == 'E') {
			buffer.append(c);
			c = it.next();
		}
		try {
			return new BigDecimal(buffer.toString());
		} catch (NumberFormatException e) {
			throw error("expected a number but was '" + buffer.toString() + "'", it); //$NON-NLS-1$ //$NON-NLS-2$;
		}
	}
}
