define(["doh/main", "../json", "../has"], function(doh, JSON, has){

	var mustThrow = function(json){
		try{
			JSON.parse(json, true);
		}catch(e){
			return;
		}
		throw new Error("Invalid JSON " + json + " should have been rejected");
	};

	doh.register("tests.json", [
		// all tests below are taken from #4.2 of the CSS3 Color Module
		function simpleString(t){ t.is("bar", JSON.parse('{"foo":"bar"}').foo); },
		function simpleTrue(t){ t.is(true, JSON.parse('{"foo":true}').foo); },
		function simpleFalse(t){ t.is(false, JSON.parse('{"foo":false}').foo); },
		function simpleNull(t){ t.is(null, JSON.parse('{"foo":null}').foo); },
		function simpleNumber(t){ t.is(3.3, JSON.parse('{"foo":3.3}', true).foo); },
		function strictString(t){ t.is("bar", JSON.parse('{"foo":"bar"}', true).foo); },
		function strictEmptyString(t){ t.is("", JSON.parse('{"foo":""}', true).foo); },
		function strictStringEsc(t){ t.is("b\n\t\"ar()", JSON.parse('{"foo":"b\\n\\t\\"ar()"}', true).foo); },
		function strictTrue(t){ t.is(true, JSON.parse('{"foo":true}', true).foo); },
		function strictFalse(t){ t.is(false, JSON.parse('{"foo":false}', true).foo); },
		function strictNull(t){ t.is(null, JSON.parse('{"foo":null}', true).foo); },
		function strictNumber(t){ t.is(3.3, JSON.parse('{"foo":3.3}', true).foo); },
		function strictNumberNeg(t){ t.is(-3.3, JSON.parse('{"foo":-3.3}', true).foo); },
		function exponentNegative(t){ t.is(3.3e-33, JSON.parse('{"foo":3.3e-33}', true).foo); },
		function exponent(t){ t.is(3.3e33, JSON.parse('{"foo":3.3e33}', true).foo); },
		function array(t){ t.is(3, JSON.parse('{"foo":[3,true,[]]}', true).foo[0]); },
		function badCall(t){ mustThrow('{"foo":alert()}'); },
		function badMath(t){ mustThrow('{"foo":3+4}'); },
		function badIndex(t){ mustThrow('{"foo":"bar"}[3]'); },
		function badKey(t){ mustThrow('{foo:"bar"}'); },
		//function badKey2(t){ mustThrow('{2:"bar"}')},
		function badUnbalanced(t){ mustThrow('['); },
		function badUnbalanced2(t){ mustThrow('}'); },
		function badType(t){ mustThrow('["foo":"bar"]'); },
		function badUnbalanced2(t){ mustThrow('}'); },
		function serializeString(t){ t.is('{"foo":"bar"}', JSON.stringify({"foo":"bar"})); },
		function serializeNull(t){ t.is('{"foo":null}', JSON.stringify({"foo":null})); },
		function serializeFunction(t){ t.is('{}', JSON.stringify({"foo":function(){}})); },
		function serializeNaN(t){ t.is('{"foo":null}', JSON.stringify({"foo":NaN})); },
		function serializeInfinity(t){ t.is('{"foo":null}', JSON.stringify({"foo":Infinity})); },
		// there is differences in how many decimals of accuracies in seconds in how Dates are serialized between browsers
		function serializeDate(t){ t.t(/1970-01-01T00:00:00.*Z/.test(JSON.parse(JSON.stringify({"foo":new Date(1)})).foo)); },
		function serializeInherited(t){
			function FooBar() { this.foo = "foo"; }
			FooBar.prototype.bar = "bar";
			t.is('{"foo":"foo"}', JSON.stringify(new FooBar()));
		},
		/*Apparently Firefox doesn't pass the key to the toJSON method*/
		function serializeToJSON(t){ t.is('{"foo":{"name":"value"}}', JSON.stringify({foo:{toJSON:function(key){return {name:"value"}; }}})); }
	]);

	if(!has("host-rhino")){
		doh.register("tests.json.circular", [
			function serializeCircular(t){
				try{
					var a = {};
					a.a = a;
					console.log("circular: " + JSON.stringify(a));
				}catch(e){
					return;
				}
				throw new Error("stringify must throw for circular references");

			}
		]);
	}

var smallDataSet = {
	prop1: null,
	prop2: true,
	prop3: [],
	prop4: 3.4325222223332266,
	prop5: 10003,
	prop6: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper",
	prop7: "sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta rutrum",
	prop8: "lacus. Etiam consequat scelerisque quam. Nulla facilisi. Maecenas luctus",
	prop9: "venenatis nulla. In sit amet dui non mi semper iaculis. Sed molestie",
	prop10: "tortor at ipsum. Morbi dictum rutrum magna. Sed vitae risus." +
		"Aliquam vitae enim. Duis scelerisque metus auctor est venenatis imperdiet." +
		"Fusce dignissim porta augue. Nulla vestibulum. Integer lorem nunc," +
		"ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in massa" +
		"bibendum suscipit. Integer eros. Nullam suscipit mauris. In pellentesque." +
		"Mauris ipsum est, pharetra semper, pharetra in, viverra quis, tellus. Etiam" +
		"purus. Quisque egestas, tortor ac cursus lacinia, felis leo adipiscing" +
		"nisi, et rhoncus elit dolor eget eros. Fusce ut quam. Suspendisse eleifend" +
		"leo vitae ligula. Nulla facilisi."
};
var smallJson = JSON.stringify(smallDataSet);

var i, mediumDataSet = [];
for(i = 0; i < 20; i++){
	mediumDataSet.push({
		prop1: null,
		prop2: true,
		prop3: false,
		prop4: 3.4325222223332266 - i,
		prop5: 10003 + i,
		prop6: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper",
		prop7: "sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta rutrum",
		prop8: "lacus. Etiam consequat scelerisque quam. Nulla facilisi. Maecenas luctus",
		prop9: "venenatis nulla. In sit amet dui non mi semper iaculis. Sed molestie",
		prop10: "tortor at ipsum. Morbi dictum rutrum magna. Sed vitae risus." +
			"Aliquam vitae enim."
	});
}
var mediumJson = JSON.stringify(mediumDataSet);

var largeDataSet = [];
for(i = 0; i < 100; i++){
	largeDataSet.push({
		prop1: null,
		prop2: true,
		prop3: false,
		prop4: 3.4325222223332266 - i,
		prop5: ["Mauris ipsum est, pharetra semper, pharetra in, viverra quis, tellus. Etiam" +
			"purus. Quisque egestas, tortor ac cursus lacinia, felis leo adipiscing",
			"nisi, et rhoncus elit dolor eget eros. Fusce ut quam. Suspendisse eleifend" +
			"leo vitae ligula. Nulla facilisi."
		],
		prop6: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper",
		prop7: "sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta rutrum",
		prop8: "lacus. Etiam consequat scelerisque quam. Nulla facilisi. Maecenas luctus",
		prop9: "venenatis nulla. In sit amet dui non mi semper iaculis. Sed molestie",
	prop10: "tortor at ipsum. Morbi dictum rutrum magna. Sed vitae risus." +
		"Aliquam vitae enim. Duis scelerisque metus auctor est venenatis imperdiet." +
		"Fusce dignissim porta augue. Nulla vestibulum. Integer lorem nunc," +
		"ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in massa" +
		"bibendum suscipit. Integer eros. Nullam suscipit mauris. In pellentesque."
	});
}
var largeJson = JSON.stringify(largeDataSet);

doh.register("tests.json.performance", [
		// all tests below are taken from #4.2 of the CSS3 Color Module
		function small(){
			var i = 10000;
			while(i-->0){
				var result = JSON.parse(smallJson);
			}
		},
		function strictSmall(){
			var i = 10000;
			while(i-->0){
				var result = JSON.parse(smallJson, true);
			}
		},
		function medium(){
			var i = 1000;
			while(i-->0){
				var result = JSON.parse(mediumJson);
			}
		},
		function strictMedium(){
			var i = 1000;
			while(i-->0){
				var result = JSON.parse(mediumJson, true);
			}
		},
		function large(){
			var i = 100;
			while(i-->0){
				var result = JSON.parse(largeJson);
			}
		},
		function strictLarge(){
			var i = 100;
			while(i-->0){
				var result = JSON.parse(largeJson, true);
			}
		}
	]);

});

