libxstats = (function () {

var url = "http://libx.org/stats/makejson.php";
var isReady = false;
var requests = 0;
var editionsCache = { };
var pending = [ ];

var userAgent = navigator.userAgent.toLowerCase();
browser = {
	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
	safari:  /webkit/.test(userAgent),
	opera:   /opera/.test(userAgent),
	msie:    /msie/.test(userAgent) && !/opera/.test(userAgent),
	mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent)
};

// check the cache to see if we've already requested data for this edition
function editionIsInCache (edition_id) {
    return (editionsCache[edition_id] !== undefined);
}
/*
 * find all div and span tags, and check each of them to see if they are in
 * the class "libxstats"
 */
function findAllLibXTags () {
    var span = document.getElementsByTagName("span");
    var div =  document.getElementsByTagName("div");
    var alltags = [ ];
    var libxtags = [ ];
    for (var i = 0; i < span.length; i++) {
        alltags.push(span[i]);
    }
    for (var i = 0; i < div.length; i++) {
        alltags.push(div[i]);
    }
    for (var i = alltags.length - 1; i >= 0; i--) {
        if (alltags[i].className == "libxstats" && alltags[i].hasAttribute("field")
            && alltags[i].hasAttribute("edition_id")) {
            libxtags.push(alltags[i]);
        }
    }
    return libxtags;
}
function processLibXTags (libxtags) {
    for (var i = 0; libxtags.length > 0; i++) {
        var elem = libxtags.pop();
        pending.push(elem);
        var edition_id = elem.getAttribute("edition_id");
        if (editionIsInCache(edition_id)) {
            libxstats.processResults(editionsCache[edition_id], false);
        }
        else {
            loadJSONFunction(edition_id);
            window.setTimeout(function () {
                processLibXTags(libxtags);
            }, 40);
            return;
        }
    }
}
function buildTable (elem, json) {
    var table = document.createElement("table");
    for (var i in json.descriptions) {
        var row = document.createElement("tr");
        var desc = document.createElement("td");
        desc.innerHTML = i;
        var data = document.createElement("td");
        data.innerHTML = json.statistics[json.descriptions[i]];
        row.appendChild(desc);
        row.appendChild(data);
        table.appendChild(row);
    }
    elem.appendChild(table)
}

function addEvent( obj, type, fn ) {
    if (obj.addEventListener) {
            obj.addEventListener( type, fn, false );
            EventCache.add(obj, type, fn);
    }
    else if (obj.attachEvent) {
            obj["e"+type+fn] = fn;
            obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
            obj.attachEvent( "on"+type, obj[type+fn] );
            EventCache.add(obj, type, fn);
    }
    else {
            obj["on"+type] = obj["e"+type+fn];
    }
}
var EventCache = function(){
    var listEvents = [];
    return {
        listEvents : listEvents,
        add : function(node, sEventName, fHandler){
            listEvents.push(arguments);
        },
        flush : function(){
            var item;
            for(var i = listEvents.length - 1; i >= 0; i--){
                item = listEvents[i];
                if(item[0].removeEventListener){
                    item[0].removeEventListener(item[1], item[2], item[3]);
                };
                if(item[1].substring(0, 2) != "on"){
                    item[1] = "on" + item[1];
                };
                if(item[0].detachEvent){
                    item[0].detachEvent(item[1], item[2]);
                };
                item[0][item[1]] = null;
            };
        }
    };
}();
addEvent(window,'unload',EventCache.flush);

function bindReady() {
	// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
	if ( document.addEventListener && !browser.opera) {
		// Use the handy event callback
		document.addEventListener( "DOMContentLoaded", function () { ready(); }, false );
    }
	
	// If IE is used and is not in a frame
	// Continually check to see if the document is ready
	if ( browser.msie && window == top ) (function(){
		if (isReady) return;
		try {
			// If IE is used, use the trick by Diego Perini
			// http://javascript.nwbox.com/IEContentLoaded/
			document.documentElement.doScroll("left");
		} catch( error ) {
			setTimeout( arguments.callee, 0 );
			return;
		}
		// and execute any waiting functions
		ready();
	})();

	if ( browser.opera )
		document.addEventListener( "DOMContentLoaded", function () {
			if (isReady) return;
			for (var i = 0; i < document.styleSheets.length; i++)
				if (document.styleSheets[i].disabled) {
					setTimeout( arguments.callee, 0 );
					return;
				}
			// and execute any waiting functions
			ready();
		}, false);

	if ( browser.safari ) {
		//var numStyles;
		(function(){
			if (isReady) return;
			if ( document.readyState != "loaded" && document.readyState != "complete" ) {
				setTimeout( arguments.callee, 0 );
				return;
			}
			// and execute any waiting functions
			ready();
		})();
	}

	// A fallback to window.onload, that will always work
    addEvent(window, "load", function () { ready(); });
}
function loadJSONFunction (edition_id) {
    var s = document.createElement("script");
    s.setAttribute("type", "text/javascript");
    var src = url +"?id="+ edition_id;
    src +="&cb=libxstats.processResults";
    s.setAttribute("src", src);
    document.documentElement.firstChild.appendChild(s);
}
function ready() {
    if (isReady) {
        return;
    }
    isReady = true;
    var libxtags = findAllLibXTags();
    processLibXTags(libxtags);
}

// when the page is loaded, load the widget
bindReady();

return {
    processResults : function (json, miss, table) {
        if (miss == true) {
            editionsCache[json.edition_id] = json;
        }
        var i = pending.length - 1;
        for (; i >= 0; i--) {
            if (pending[i].getAttribute("edition_id") == json.edition_id) {
                break;
            }
        }
        var fieldName = pending[i].getAttribute("field");
        if (fieldName == "all") {
            buildTable(pending[i], json);
        }
        else {
            pending[i].innerHTML = json.statistics[fieldName];
        }
        pending.splice(i, 1);       
    },
}

}
)();
