/*
 //##copyright
//	Copyright (c) 2002 JSON.org
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//copyright##

    json.js

    This file adds these methods to JavaScript:

        object.toJSONString(prettyPrint)

            This method produces a JSON text from an object. The
            object must not contain any cyclical references.

        array.toJSONString(prettyPrint)

            This method produces a JSON text from an array. The
            array must not contain any cyclical references.

        string.parseJSON()

            This method parses a JSON text to produce an object or
            array. It will return false if there is an error.

+           added prettyPrint argument
            prettyPrint ... if set to true the resulting string will be formated
                            with tabs and returns to be more human readable.
                            by Matthias.Platzer@knallgrau.at

*/
var JSON = (function () {
    var pPr = false;
    var lvl;
    var indentLevel = 0;
    var indent = function(a) {
        if (!pPr) return a;
        a[a.length] = pPr==2 ?  ('                    ').substr(0,indentLevel*2) : '<span style="padding-left:'+(indentLevel*15)+'px;">&nbsp;</span>';
        return a;
    };

    var newline = function(a) {
        if (pPr) {
        	a[a.length] = pPr==2 ? '\n' : '<br />';
        }
        return a;
    };

    var highlight = function(a) {
    	if (pPr && pPr!=2) return '<b>'+a+'</b>';
    	return a;
    }
	// called if pPr = true and a is a string
    var pre = function(a) {
    	if (a.indexOf('<')>-1 && pPr!=2) {
			return '<br /><textarea readonly="1" style="width:100%;height:10em;">'+(a.replace(/</g,'&lt;'))+'</textarea>';
    	}
    	return '"'+a+'"';
    }

    var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        s = {
            array: function (x) {
                var a = ['['], b, f, i, l = x.length, v;
                a = newline(a);
                indentLevel++;
                for (i = 0; i < l; i += 1) {
                    v = x[i];
                    f = s[typeof v];
                    if (f) {
                        v = f(v);
                        if (typeof v == 'string') {
                            if (b) {
                                a[a.length] = ',';
                                a = newline(a);
                            }
                            a = indent(a);
                            a[a.length] = v;
                            b = true;
                        }
                    }
                }
                indentLevel--;
                a = newline(a);
                a = indent(a);
                a[a.length] = ']';
                return a.join('');
            },
            'boolean': function (x) {
                return String(x);
            },
            'null': function (x) {
                return "null";
            },
            number: function (x) {
                return isFinite(x) ? String(x) : 'null';
            },
            object: function (x) {
                if (x) {
                    if (x instanceof Array) {
                        return s.array(x);
                    }
                    if (pPr) {
	                    if (x.nodeType && x.nodeName) {
	                    	return x.nodeName;
	                    }
	                    if (indentLevel>lvl) return '. . . .';
                    }
                    var a = ['{'], b, f, i, v;
                    a = newline(a);
                    indentLevel++;
                    for (i in x) {
                        v = x[i];
                        f = s[typeof v];
                        if (f) {
                            //v = f(v);
                            v =  pPr ? (typeof v == 'string' ? pre(v):f(v)): f(v);

                            if (typeof v == 'string') {
                                if (b) {
                                    a[a.length] = ',';
                                    a = newline(a);
                                }
                                a = indent(a);
                                a.push(highlight(s.string(i)), ((pPr) ? ' : ' : ':'), v);
                                b = true;
                            }
                        }
                    }
                    indentLevel--;
                    a = newline(a);
                    a = indent(a);
                    a[a.length] = '}';
                    return a.join('');
                }
                return 'null';
            },
            string: function (x) {
                if (/["\\\x00-\x1f]/.test(x)) { //" { just to make the zend parser happy!
                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                        var c = m[b];
                        if (c) {
                            return c;
                        }
                        c = b.charCodeAt();
                        return '\\u00' +
                            Math.floor(c / 16).toString(16) +
                            (c % 16).toString(16);
                    });
                }
                return '"' + x + '"';
            }
        };

    // cannot use prototype for emuneratable objects / arrays
//    Object.prototype.toJSONString = function (prettyPrint) {
//        pPr = prettyPrint;
//        return s.object(this);
//    };
//
//    Array.prototype.toJSONString = function (prettyPrint) {
//        pPr = prettyPrint;
//        return s.array(this);
//    };
//
//    };
	return {
		stringify: function(a, b, c) {
			pPr = b;
			lvl = c || 100;
			if(a==null || typeof(a)=="undefined") return a;
			switch(a.constructor) {
				case Array:
					return s.array(a);
				case String:
					return s.string(a);
				case Boolean:
					return s.boolean(a);
				case Number:
					return s.number(a);
				// all other object types
				case Object:
				default:
					return s.object(a);
			}
		},
		parse: function(a) {
			if (a.constructor == String) {
			    try {
			    	return (eval('(' + a + ')'));
//			        return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
//			                a.replace(/"(\\.|[^"\\])*"/g, ''))) &&
//			            eval('(' + a + ')');
			    } catch (e) {
			        return false;
			    }
			}
			return false;
		}
	};
})();
