/* window.JSON; http://www.JSON.org/ */
if (!this.JSON) {
    this.JSON = {}
}(function () {
    function f(n) {
        return n < 10 ? '0' + n : n
    }
    if (typeof Date.prototype.toJSON !== 'function') {
        Date.prototype.toJSON = function (key) {
            return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null
        };
        String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) {
            return this.valueOf()
        }
    }
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap, indent, meta = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"': '\\"',
            '\\': '\\\\'
        },
        rep;

    function quote(string) {
            escapable.lastIndex = 0;
            return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
                var c = meta[a];
                return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)
            }) + '"' : '"' + string + '"'
        }
    function str(key, holder) {
            var i, k, v, length, mind = gap,
                partial, value = holder[key];
            if (value && typeof value === 'object' && typeof value.toJSON === 'function') {
                    value = value.toJSON(key)
                }
            if (typeof rep === 'function') {
                    value = rep.call(holder, key, value)
                }
            switch (typeof value) {
                case 'string':
                    return quote(value);
                case 'number':
                    return isFinite(value) ? String(value) : 'null';
                case 'boolean':
                case 'null':
                    return String(value);
                case 'object':
                    if (!value) {
                        return 'null'
                    }
                    gap += indent;
                    partial = [];
                    if (Object.prototype.toString.apply(value) === '[object Array]') {
                        length = value.length;
                        for (i = 0; i < length; i += 1) {
                            partial[i] = str(i, value) || 'null'
                        }
                        v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']';
                        gap = mind;
                        return v
                    }
                    if (rep && typeof rep === 'object') {
                        length = rep.length;
                        for (i = 0; i < length; i += 1) {
                            k = rep[i];
                            if (typeof k === 'string') {
                                v = str(k, value);
                                if (v) {
                                    partial.push(quote(k) + (gap ? ': ' : ':') + v)
                                }
                            }
                        }
                    } else {
                        for (k in value) {
                            if (Object.hasOwnProperty.call(value, k)) {
                                v = str(k, value);
                                if (v) {
                                    partial.push(quote(k) + (gap ? ': ' : ':') + v)
                                }
                            }
                        }
                    }
                    v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}';
                    gap = mind;
                    return v
                }
        }
    if (typeof JSON.stringify !== 'function') {
            JSON.stringify = function (value, replacer, space) {
                var i;
                gap = '';
                indent = '';
                if (typeof space === 'number') {
                    for (i = 0; i < space; i += 1) {
                        indent += ' '
                    }
                } else if (typeof space === 'string') {
                    indent = space
                }
                rep = replacer;
                if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {
                    throw new Error('JSON.stringify');
                }
                return str('', {
                    '': value
                })
            }
        }
    if (typeof JSON.parse !== 'function') {
            JSON.parse = function (text, reviver) {
                var j;

                function walk(holder, key) {
                    var k, v, value = holder[key];
                    if (value && typeof value === 'object') {
                        for (k in value) {
                            if (Object.hasOwnProperty.call(value, k)) {
                                v = walk(value, k);
                                if (v !== undefined) {
                                    value[k] = v
                                } else {
                                    delete value[k]
                                }
                            }
                        }
                    }
                    return reviver.call(holder, key, value)
                }
                text = String(text);
                cx.lastIndex = 0;
                if (cx.test(text)) {
                    text = text.replace(cx, function (a) {
                        return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)
                    })
                }
                if (/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
                    j = eval('(' + text + ')');
                    return typeof reviver === 'function' ? walk({
                        '': j
                    }, '') : j
                }
                throw new SyntaxError('JSON.parse');
            }
        }
}());

/* CSS Http Request; http://www.nb.io/hacks/csshttprequest */

(function(){
    var chr = window.CSSHttpRequest = {};
    
    
    chr.id = 0;
    chr.requests = {};
    chr.MATCH_ORDINAL = /#c(\d+)/;
    chr.MATCH_URL = /url\("?data\:[^,]*,([^")]+)"?\)/;
    
    
    chr.get = function(url, callback) {
        var id = ++chr.id;
        var iframe = document.createElement( "iframe" );
        iframe.style.position = "absolute";
        iframe.style.left = iframe.style.top = "-1000px";
        iframe.style.width = iframe.style.height = 0;
        document.documentElement.appendChild(iframe);
        var r = chr.requests[id] = {
            id: id,
            iframe: iframe,
            document: iframe.contentDocument || iframe.contentWindow.document,
            callback: callback
        };
        
        r.document.open("text/html", false);
        r.document.write("<html><head>");
        r.document.write("<link rel='stylesheet' type='text/css' media='print, csshttprequest' href='" + chr.escapeHTML(url) + "' />");
        r.document.write("</head><body>");
        r.document.write("<script type='text/javascript'>");
        r.document.write("(function(){var w = window; var p = w.parent; p.CSSHttpRequest.sandbox(w); w.onload = function(){p.CSSHttpRequest.callback('" + id + "');};})();");
        r.document.write("</script>");
        r.document.write("</body></html>");
        r.document.close();
    };
    
    
    chr.sandbox = function(w) {
    };
        
    
    chr.callback = function(id) {
        var r = chr.requests[id];
        var data = chr.parse(r);
        r.callback(data);
        window.setTimeout(function() {
            var r = chr.requests[id];
            try { r.iframe.parentElement.removeChild(r.iframe); } catch(e) {};
            delete chr.requests[id];
        }, 0);
    };
    
    chr.parse = function(r) {
        var data = [];
        
        // Safari, IE and same-domain Firefox
        try {
            var rules = r.document.styleSheets[0].cssRules || r.document.styleSheets[0].rules;
            for(var i = 0; i < rules.length; i++) {
                try {
                    var r = rules.item ? rules.item(i) : rules[i];
                    var ord = r.selectorText.match(chr.MATCH_ORDINAL)[1];
                    var val = r.style.backgroundImage.match(chr.MATCH_URL)[1];
                    data[ord] = val;
                } catch(e) {}
            }
        }
        
        // catch same-domain exception
        catch(e) {
            r.document.getElementsByTagName("link")[0].setAttribute("media", "screen");
            var x = r.document.createElement("div");
            x.innerHTML = "foo";
            r.document.body.appendChild(x);
            var ord = 0;
            try {
                while(1) {
                    x.id = "c" + ord;
                    var style = r.document.defaultView.getComputedStyle(x, null);
                    var bg = style["background-image"] || style.backgroundImage || style.getPropertyValue("background-image");
                    var val = bg.match(chr.MATCH_URL)[1];
                    data[ord] = val;
                    ord++;
                }
            } catch(e) {}
        }
        
        return decodeURIComponent(data.join(""));
    };
    
    
    chr.escapeHTML = function(s) {
        return s.replace(/([<>&""''])/g,
            function(m, c) {
                switch(c) {
                    case "<": return "&lt;";
                    case ">": return "&gt;";
                    case "&": return "&amp;";
                    case '"': return "&quot;";
                    case "'": return "&apos;";
                }
                return c;
            });
    };
})();

/* Lucuma CSS Long Polling */

var Lucuma = function(url)
{
	if (typeof(arguments.callee.id)!==typeof(1)) { arguments.callee.id = -1; }
	if (!arguments.callee.connections) { arguments.callee.connections = []; }
	this.id = ++arguments.callee.id;
	this.queries = {};
	this.url = url;
	this.cache = false;
	this.paused = false;
	this.terminated = false;
	this.attempts = 0;
	this.passes = 0;
	this.duration = 100;
	this._uri = function (queries)
	{
		if (queries === undefined) { return ""; }
		var b = "", i = 0, len = -1, value;
		for (value in queries) { if (queries.hasOwnProperty(value)) { len++; } }
		for (value in queries) { b += escape(value) + "=" + escape(queries[value]); if (++i <= len) { b += "&"; } }
		return "" + b;
	};
	this.onresponse = function (){};
	this.callback = function (response)
	{
		self.passes++;
		self.onresponse(response);
		if (typeof(self.request)===typeof(function (){}))
		{
			if( self.duration === 0 ) { self.request(); }
			else if ( self.duration >= 0 ) {
			try { window.setTimeout(self.request, self.duration); } catch(err) { self.request(); }}
		}
	};
	var self = this;
	this.request = function (url, callbak)
	{
		if (self.terminated) { return; }
		if (self.paused) { return; }
		if (!self.cache) { self.queries.NoCaching = Math.floor(Math.random() * 10000); }
		CSSHttpRequest.get(((url) ? url : self.url)+'?'+self._uri(self.queries), (callbak) ? callbak : self.callback);
		self.attempts++;
		return true;
	};
	this.ontermination = function (){};
	this.getConnectionById = function (id) { return (Lucuma.connections[id]) ? Lucuma.connections[id] : null; };
	this.connection = 
	{
		establish : function (){ self.request(); },
		terminate : function (){ if (arguments.callee.dead) { return; } arguments.callee.dead = true; self.ontermination(); self.terminated = true; },
		suspend : function () { self.paused = true; },
		resume : function () { self.paused = false; self.request(); }
	};
	arguments.callee.connections.push(this);
	return this;
};
