function preloader(json) {
	if(json !== null && !window.preloaded.hasOwnProperty(json.id)) {
		if(!$('preloader')) {
			new Element('div', {
				'id': 'preloader',
				'style': 'height: 1px;width:1px;position:absolute;left:-9999px;'
			}).inject(document.body);
		}
		
		if(typeof json.font_config == "string") {
			var fonts = JSON.decode(json.font_config);
			if(fonts.length > 0) {
				Expo.load_fonts(fonts);
			}
		}
		
		$('preloader').innerHTML = json.render;
		window.preloaded[json.id] = true;
	}
}

function render_item(json) {
	if(!json) { return; }
	
	$('textblocks_overlay').removeClass('videos');
	
	
	if(typeof json.font_config == "string") {
		var fonts = JSON.decode(json.font_config);
		if(fonts.length > 0) {
			Expo.load_fonts(fonts);
		}
	}

	var pnl = $('bottom-bar').getElements('a'),
		ors = $('bottom-bar').getElements('span');
	if(json.previous_id === null) {
		json.previous_id = '';
	}
	pnl[1].href = '/expo/' + json.url_key + '/' + json.next_id;
	pnl[0].href = '/expo/' + json.url_key + '/' + json.previous_id;

	$('item_under').innerHTML = json.render;
	$('textblocks_overlay').innerHTML = '<a class="pagelink" href="' + pnl[1].href + '" id="next_page_click"></a>';
	$('textblocks_overlay').innerHTML += json.textblock;
	$('item_under').getElements('script').each(function(scr) {
		eval(scr.innerText);
	});
	
	window.current_id = json.id;
	
	$('next_page_click').addEvent('click', page_click);
	
	ors[0].innerHTML = pad(json.order, 2) + '/' + pad(json.items.number, 2);
	ors[1].innerHTML = json.title;
	if(json.item_title !== null) {
		ors[1].innerHTML += ' &ndash; ' + json.item_title;
	}
	
	window.location.hash = json.id;

	$$('.textblock').addClass('scroll');
	custom_scrollbars();
	
	var downloads = $$('a.download');
	if(downloads.length > 0) {
		downloads.each(function(item) {
			item.getParent('.textblock').addClass('waytop');
			item.setAttribute('target', '_blank');
		});
	}
	
	if(window.PIE) {
		$$('.textblock').each(function(block) {
            PIE.attach(block);
		});
	}
	
	fix_browsers();
	
	if(json.next_id) {
		load_page('/expo/' + json.url_key + '/' + json.next_id + '.json', preloader);
	}
}

function load_page(xhrUrl, render) {
	if(typeof render == 'undefined') { render = render_item; }
	if(!window.cache.hasOwnProperty(xhrUrl) || window.cache[xhrUrl] === null) {
		new Request.JSON({
			url: xhrUrl,
			method: 'get',
			onComplete: function(json) { window.cache[xhrUrl] = json; if(render) {render(json); } }
		}).send();
	} else {
		render(window.cache[xhrUrl]);
	}
}

function pad(num, count) {
	var lenDiff = count - String(num).length;
	var padding = "";

	if (lenDiff > 0)
	  while (lenDiff--)
	    padding += "0";

	return padding + num;
}

/* Cross-Browser Split 1.0.1
(c) Steven Levithan <stevenlevithan.com>; MIT License
An ECMA-compliant, uniform cross-browser split method */

var cbSplit;

// avoid running twice, which would break `cbSplit._nativeSplit`'s reference to the native `split`
if (!cbSplit) {

cbSplit = function (str, separator, limit) {
    // if `separator` is not a regex, use the native `split`
    if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
        return cbSplit._nativeSplit.call(str, separator, limit);
    }

    var output = [],
        lastLastIndex = 0,
        flags = (separator.ignoreCase ? "i" : "") +
                (separator.multiline  ? "m" : "") +
                (separator.sticky     ? "y" : ""),
        separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy
        separator2, match, lastIndex, lastLength;

    str = str + ""; // type conversion
    if (!cbSplit._compliantExecNpcg) {
        separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt
    }

    /* behavior for `limit`: if it's...
    - `undefined`: no limit.
    - `NaN` or zero: return an empty array.
    - a positive number: use `Math.floor(limit)`.
    - a negative number: no limit.
    - other: type-convert, then use the above rules. */
    if (limit === undefined || +limit < 0) {
        limit = Infinity;
    } else {
        limit = Math.floor(+limit);
        if (!limit) {
            return [];
        }
    }

    while (match = separator.exec(str)) {
        lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser

        if (lastIndex > lastLastIndex) {
            output.push(str.slice(lastLastIndex, match.index));

            // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups
            if (!cbSplit._compliantExecNpcg && match.length > 1) {
                match[0].replace(separator2, function () {
                    for (var i = 1; i < arguments.length - 2; i++) {
                        if (arguments[i] === undefined) {
                            match[i] = undefined;
                        }
                    }
                });
            }

            if (match.length > 1 && match.index < str.length) {
                Array.prototype.push.apply(output, match.slice(1));
            }

            lastLength = match[0].length;
            lastLastIndex = lastIndex;

            if (output.length >= limit) {
                break;
            }
        }

        if (separator.lastIndex === match.index) {
            separator.lastIndex++; // avoid an infinite loop
        }
    }

    if (lastLastIndex === str.length) {
        if (lastLength || !separator.test("")) {
            output.push("");
        }
    } else {
        output.push(str.slice(lastLastIndex));
    }

    return output.length > limit ? output.slice(0, limit) : output;
};

cbSplit._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group
cbSplit._nativeSplit = String.prototype.split;

} // end `if (!cbSplit)`

// for convenience...
String.prototype.split = function (separator, limit) {
    return cbSplit(this, separator, limit);
};


function page_click(e) {
	if(e.target.href.match(/save_progress/)) { return; }
	e.stopPropagation();
	e.stop();

	var a;
	if(e.target.get('tag') != 'a') {
		a = e.target.parentNode.parentNode;
	} else { a = e.target; }

	if(a.href.substring(0, 4) != 'http') {
		a.href = 'http://' + window.location.hostname + a.href;
	}

	var parts = a.href.split(/\//);
	if(parts[5] === '') { parts[5] = 'first'; }
	else if (parts[5] == 'save_progress') { window.location = a.href; }
	var xhrUrl = '/expo/' + parts[4] + '/' + parts[5] + '.json';
	load_page(xhrUrl);
}

function check_hash() {
	if(window.location.hash.substring(1) !== "") {
		var id = window.location.hash.substring(1);
		
		if(typeof window.current_id != "undefined" && window.current_id !== id) {
			var parts = window.location.toString().split('/'),
				xhrUrl = '/expo/' + parts[4] + '/' + id + '.json';

			load_page(xhrUrl);
		}
		
	}
}

window.addEvent('domready', function() {
	if(!Browser.Features.xhr) { return; }
	
	
	window.cache = {};
	window.preloaded = {};
	
	if(window.location.hash.substring(1) !== "") {
		var parts = window.location.toString().split('/'),
			xhrUrl = '/expo/' + parts[4] + '/' + window.location.hash.substring(1) + '.json';

		load_page(xhrUrl);
	}
	
	check_hash.periodical(100);
	
	
	$$('.pagelink').addEvent('click', page_click);
	
});
