/**
 * 
 */
package org.richfaces.json;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import junit.framework.TestCase;

/**
 * @author Nick Belaevski - nbelaevski@exadel.com
 * created 12.04.2007
 * 
 */
public class JsonTest extends TestCase {

	/**
	 * @param name
	 */
	public JsonTest(String name) {
		super(name);
	}

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();
	}

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {
		super.tearDown();
	}

	public void testMap() throws Exception {
		JSONMap map = new JSONMap("{text: 12, moreData: { key: value, key1: 23.04 }}");
		assertEquals(12, ((Integer) map.get("text")).intValue());
		assertEquals(2, map.size());
		
		Map innerMap = (Map) map.get("moreData");
		assertEquals("value", innerMap.get("key"));
		assertEquals(23.04, ((Double) innerMap.get("key1")).doubleValue(), 0);
		assertEquals(2, innerMap.size());
	}

	public void testCollection() throws Exception {
		JSONCollection collection = new JSONCollection("[text, { key: value, key1: 23.04 }, [1, a, 3]]");
		assertEquals(3, collection.size());

		Iterator iterator = collection.iterator();
		assertTrue(iterator.hasNext());
		
		assertEquals("text", iterator.next());
		assertTrue(iterator.hasNext());
		
		Map innerMap = (Map) iterator.next();
		assertTrue(iterator.hasNext());

		assertEquals("value", innerMap.get("key"));
		assertEquals(23.04, ((Double) innerMap.get("key1")).doubleValue(), 0);
		assertEquals(2, innerMap.size());
		
		Collection innerCollection = (Collection) iterator.next();
		assertEquals(3, innerCollection.size());
		Iterator innerIterator = innerCollection.iterator();
		
		assertTrue(innerIterator.hasNext());
		assertEquals(1, ((Integer) innerIterator.next()).intValue());
		assertTrue(innerIterator.hasNext());
		assertEquals("a", innerIterator.next());
		assertTrue(innerIterator.hasNext());
		assertEquals(3, ((Integer) innerIterator.next()).intValue());
		assertFalse(innerIterator.hasNext());
		
		assertFalse(iterator.hasNext());
	}

	public void testNewCollection() throws Exception {
		JSONCollection collection = new JSONCollection();
		assertTrue(collection.isEmpty());
	}

	public void testNewMap() throws Exception {
		JSONMap map = new JSONMap();
		assertTrue(map.isEmpty());
	}
	
	public void testMapAddiition() throws Exception {
		JSONMap map = new JSONMap();
		Set set = map.entrySet();
		set.add(new JsonTestMockMapEntry("boolean", new Boolean(true)));
		set.add(new JsonTestMockMapEntry("double", new Double(23.45)));
		set.add(new JsonTestMockMapEntry("integer", new Integer(56)));
		set.add(new JsonTestMockMapEntry("long", new Long(89)));
		set.add(new JsonTestMockMapEntry("string", "testString"));

		HashSet hashSet = new HashSet();

		hashSet.add("15");
		hashSet.add(new Double(45.01));
	
		HashSet etalonSet = (HashSet) hashSet.clone();

	
		HashMap hashMap = new HashMap();

		hashMap.put("16", new Boolean(false));
		hashMap.put("key", new Double(145.01));
	
		HashMap etalonMap = (HashMap) hashMap.clone();

		set.add(new JsonTestMockMapEntry("collection", hashSet));
		set.add(new JsonTestMockMapEntry("map", hashMap));
	
		assertEquals(Boolean.TRUE, map.get("boolean"));
		assertEquals(new Double(23.45), map.get("double"));
		assertEquals(new Integer(56), map.get("integer"));
		assertEquals(new Long(89), map.get("long"));
		assertEquals("testString", map.get("string"));
		
		Collection collection = (Collection) map.get("collection");
		assertTrue(etalonSet.containsAll(collection));
		etalonSet.removeAll(collection);
		assertTrue(etalonSet.isEmpty());
		
		assertEquals(etalonMap, map.get("map"));
	}

}

class JsonTestMockMapEntry implements Map.Entry {

	private Object key;
	private Object value;
	
	
	
	public JsonTestMockMapEntry(Object key, Object value) {
		super();
		this.key = key;
		this.value = value;
	}

	public Object getKey() {
		return key;
	}

	public Object getValue() {
		return value;
	}

	public Object setValue(Object newValue) {
		Object oldValue = value;
		value = newValue;
		return oldValue;
	}
	
}