function __p(e, t, fudge) {
	if ('undefined' != typeof(fudge)) {
		t.top += fudge[0];
		t.left += fudge[1];
		t.width += fudge[2];
		t.height += fudge[3];
	}
	for (s in t) {
		e.style[s] = t[s] + 'px';
	}
};

Reader = Class.create();
Reader.prototype = {
	curPage: 0,
	margin_x: 17,
	margin_y: 13,
	// this is full width / usable width (usable width has - 2 to compensate extra
	// padding on top and bottom to keep AA
	wasteFactor: 624/(590 - 16),
	cap_w: 624,
	cap_h: 16,
	barsVisible: true,
	hasBars: true,

	initialize: function() {
		this.hasBars = $('footer') ? true : false;
		if (hideBars) {
            this._toggleBars(false);
		}
		if (!this.hasBars) {
			this.barsVisible = false;
		}
		if (typeof lockSize != 'undefined') {
			this.lockSize = lockSize;
		} else {
			this.lockSize = null;
		}

		$$('.hint').invoke('hide');
		if (starterMode) {
			loadData.pages[1].hint = '';
			loadData.pages[3].hint = '';
		}
		this.container = $('content');
		this.o_top = $('overlay_top');
		this.o_top_main = $('overlay_top_main');
		this.o_top_cover = $('overlay_top_cover');
		this.bg = $('bookbg');
		this.c_left = $('leftcontent');
		this.instruct = $('instructions');
		this.c_right = $('rightcontent');
		this.h_left = $('hideleft');
		this.h_right = $('hideright');
		this.h_left.hide();
		this.h_right.hide();

		this.c_left.makeClipping();
		this.c_right.makeClipping();

        if (this.hasBars) {
			if (!starterMode) {
				$('menu_exit').hide();
				$('menu_zoom').hide();
				if (!buyUrl && $('menu_buy')) {
					$('menu_buy').hide();
				}
				$('menu_share').hide();
				//this._toggleBars();
				Event.observe('footer', 'click', this._handleMenu.bindAsEventListener(this));
			} else {
				Event.observe('footer', 'click', this._handleStarterMenu.bindAsEventListener(this));
			}
        }

		//  make the needed width wider by the amount of percent wasted on sides
		this.realAspect = loadData.height / loadData.width;
		this.aspect = this.realAspect / this.wasteFactor;

		// position things
		this.updateContainer();

		// load up listeners
		Event.observe(window, 'resize', this.updateContainer.bindAsEventListener(this));
		Event.observe('arrow_left', 'click', this.prev.bindAsEventListener(this));
		Event.observe('arrow_right', 'click', this.next.bindAsEventListener(this));
		Event.observe(document, 'keypress', this._handleKeys.bindAsEventListener(this));

		if (Prototype.Browser.IE) {
			$$('body')[0].setStyle({background: '#444455' });
		}
	},

	_toggleBars: function(show) {
		if (!this.hasBars) return;
		if (typeof show != 'undefined') {
			if (show) {
	            $('header').show();
	            $('footer').show();
	            this.barsVisible = true;
			} else {
	            $('header').hide();
	            $('footer').hide();
	            this.barsVisible = false;
			}
		} else {
	        if (hideBars) {
	            $('header').toggle();
	            $('footer').toggle();
	            this.barsVisible = !this.barsVisible;
	        }
		}
	},

	doImageReplacements: function() {
		if (!Prototype.Browser.IE) return;
		this.o_top_main.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.o_top_main.src + '\', sizingMethod=\'scale\')';
		this.o_top_main.src = imageBase + 'blank.gif';
		this.o_top_cover.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.o_top_cover.src + '\', sizingMethod=\'scale\')';
		this.o_top_cover.src = imageBase + 'blank.gif';
	},

	_handleKeys: function(evt) {
		switch(evt.keyCode) {
			case Event.KEY_UP:
			case Event.KEY_LEFT:
			case Event.KEY_PAGEUP:
				this.prev(evt);
				break;
			case Event.KEY_DOWN:
			case Event.KEY_RIGHT:
			case Event.KEY_PAGEDOWN:
				this.next(evt);
				break
		}
	},

	_handleStarterMenu: function(evt) {
		var el = Event.element(evt);
		if (!el.hasClassName('button')) el = el.up('.button');
		if (!el || !el.id) return;
		switch (el.id) {
			case 'menu_exit': this._exitFullscreen(); break;
			case 'menu_use_starter': document.location = continueUrl; break;
		}
	},

	_handleMenu: function(evt) {
		var el = Event.element(evt);
		if (el.nodeName.toLowerCase() != 'li') el = el.up('li');
		if (!el || !el.id) return;
		switch (el.id) {
			case 'menu_fullscreen': this._makeFullscreen(); break;
			case 'menu_exit': this._exitFullscreen(); break;
			case 'menu_use_starter': document.location = continueUrl; break;
			case 'menu_buy': this.goToLink(buyUrl); break;
		}
	},

	_makeFullscreen: function() {
		try {
			if (window.parent && 'function' == typeof(window.parent.makeBookFullscreen)) {
				this._toggleBars();
				window.parent.makeBookFullscreen();
				$('menu_fullscreen').hide();
				$('menu_exit').show();
				window.focus();
			}
		} catch (_e) {}
	},

	_exitFullscreen: function() {
		try {
			if (window.parent && 'function' == typeof(window.parent.makeBookNormal)) {
				if (starterMode) {
					window.parent.closeEditor(false);
				} else {
	                this._toggleBars();
					window.parent.makeBookNormal();
					$('menu_fullscreen').show();
					$('menu_exit').hide();
				}
				return;
			}
		} catch (_e) {}
		document.location = returnUrl;
	},

	goToLink: function(url) {
		try {
			if (window.parent) {
				window.parent.document.location = url;
			} else {
				document.location = url;
			}
		} catch (e) {
			// if we're embedded, the above will cause an exception, we we will open a window
			window.open(url, 'tikatokwindow', '');
		}
	},

	_findPos: function(obj, limit) {
		if (!limit) limit = null;
		var curleft = curtop = 0;
		if (obj.offsetParent) {
			do {
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
			} while ((obj != limit) && (obj = obj.offsetParent)); // != null, up to an including limit
		}
		return [curleft,curtop];
	},

	_makeClickable: function(page, a) {
		var div = document.createElement('div');
		div.className = '__clickable'
		$('content').appendChild(div);
		var container = a.up('div');
		var pos = this._findPos(container, page);
		var size = container.getDimensions();
		div.setStyle({position: 'absolute', left: pos[0] + 'px', top: pos[1] + 'px', width: size.width + 'px', height: size.height + 'px', zIndex: 30000});
		Event.observe(div, 'click', this.goToLink.bind(this, a.href));
	},

	checkForLinks: function() {
		$$('__clickable').invoke('remove');
		$$('#leftcontent a').each(this._makeClickable.bind(this, this.c_left));
		$$('#rightcontent a').each(this._makeClickable.bind(this, this.c_right));
	},

	_updatePages: function() {
		if (this.curPage == 0 || this.curPage == loadData.pages.length - 1) {
			this.o_top_main.hide();
			this.o_top_cover.show();
			if (this.curPage == 0) {
				this.clearNode(this.c_left);
				this.updatePage(this.c_right, this.curPage);
				this.h_left.show();
				if (this.instruct) this.instruct.show();
			} else {
				this.clearNode(this.c_right);
				this.updatePage(this.c_left, this.curPage);
				this.h_right.show();
				if (this.instruct) this.instruct.hide();
			}
		} else {
			this.o_top_main.show();
			this.o_top_cover.hide();
			this.updatePage(this.c_left, this.curPage);
			this.updatePage(this.c_right, this.curPage+1);
			this.h_left.hide();
			this.h_right.hide();
			if (this.instruct) this.instruct.hide();
		}
		if (this.findLinks) window.clearTimeout(this.findLinks);
		this.findLinks = window.setTimeout(this.checkForLinks.bind(this), 200);
	},

	prev: function(evt) {
		Event.stop(evt);
		if (this.curPage <= 0) return;
		this.curPage -= 2;
		if (this.curPage < 0) this.curPage = 0;
		this._updatePages();
	},

	next: function(evt) {
		Event.stop(evt);
		if (this.curPage >= loadData.pages.length-2) return;
		this.curPage += (this.curPage != 0) ? 2 : 1;
		this._updatePages();
	},

	getViewportSize: function() {
		if (this.lockSize) return [this.lockSize[0], this.lockSize[1]];
		var res = [0, 0];
		if ('undefined' != typeof window.innerWidth) {
			// standards compliant browsers
			res[0] = window.innerWidth;
			res[1] = window.innerHeight;
		} else {
			// IE6 uses either documentElement or document's body
			var d = document.documentElement;
			if ('undefined' == typeof document.documentElement) {
				d = document.getElementsByTagName('body')[0];
			}
			res[0] = d.clientWidth;
			res[1] = d.clientHeight;
		}

		return res;
	},

	updateContainer: function() {
		try {
			if (window.parent && typeof(window.parent.tikatok_fullscreen) != 'undefined') {
				this._toggleBars(window.parent.tikatok_fullscreen);
			}
		} catch (_e0) {};

		var vs = this.getViewportSize();
		var params = {left: 0, top: 50, width: vs[0], height: vs[1] - (this.hasBars && this.barsVisible ? 32 : 0)};
		if (this.hasBars) {
			params.left = this.margin_x;
			params.width -= this.margin_x*2;
		}
		if (this.barsVisible) {
			params.height -= 50;
		} else {
			params.top = 0;
		}
		__p(this.container, params);

		var containerWidth = params.width;
		var containerHeight = params.height - (starterMode ? 70 : 0);
		var sx = containerWidth;// - 48; // for buttons
		//var sy = containerHeight - (this.margin_y * 5); // Math.round(this.margin_y * 2 * (this.container.getHeight()/300))
		var sy = containerHeight - Math.round(this.margin_y * 2 * (this.container.getHeight()/300));

		var a = this.aspect * 0.5; // because we show 2-page spreads
		var x, y;
		if (a <= 1) { // wider than tall
			y = sy;
			x = y / a;
			// try to fit the width
			if (x > sx) {
				x = sx;
				y = x * a;
			}
		} else { // taller than wide
			x = sx;
			y = x * a;
		}

		var cw = Math.round(containerWidth / 2);
		var ch = Math.round(containerHeight / 2);
		var halfHeight = Math.round(y/2);
		var halfWidth = Math.round(x/2);
		x = halfWidth * 2;
		y = halfHeight * 2;

		// top
		var cap_height = Math.round(this.cap_h*(x/this.cap_w));
		if (this.lockSize) {
			__p(this.o_top, {width: this.lockSize[0], height: this.lockSize[1], left: 0, top: 0});
		} else {
			params = {width: x, height: y+cap_height*2, left: cw - halfWidth, top: ch - halfHeight - cap_height };
			__p(this.o_top, params);
		}

		// bg (extends across)
		params.top += 1;
		params.height -= 2;
		params.left += 1;
		params.width -= 3;
		__p(this.bg, params);

		// left content
		params.top += 2;
		params.height -= 4;
		params.width = Math.round(params.height / this.realAspect)-1;
		params.left = cw - params.width;
		__p(this.c_left, params);
		if (this.instruct) {
			__p(this.instruct, params);
		}

		// right content
		params.left = cw;
		__p(this.c_right, params);

		// reload pages to fix font sizes
		this._updatePages();

		// hide fullscreen if can't access parent to control this frame
		if (this.hasBars) {
			var failedFullscreen = true;
			try {
				if (!starterMode && window.parent && 'undefined' != typeof(window.parent.tikatok_fullscreen)) {
					failedFullscreen = false;
					if (window.parent.tikatok_fullscreen) {
						$('menu_fullscreen').hide();
						$('menu_exit').show();
						window.focus();
					}
				}
			} catch (e) { }
			if (failedFullscreen) {
				if (!starterMode) {
					$('menu_fullscreen').hide();
					$('menu_exit').hide();
					$('menu_popout').show();
				}
			}
                        /*
                        // not showing the logo in fullscreen mode now
                        else {
				$('logolink').hide();
			}
                        */
		}
	},

	clearNode: function(el) {
		$(el).immediateDescendants().each(function(child) { el.removeChild(child); });
		$(el).setStyle({background: 'rgb(255,255,255)' });
	},

	updatePage: function(el, pgIndex) {
		this.clearNode(el);
		if (pgIndex >= loadData.pages.length) return;
		var pageData = loadData.pages[pgIndex];

		var w = el.getWidth();
		var h = el.getHeight();
		el.style.backgroundColor = pageData.bg ? pageData.bg : 'rgb(255,255,255)';

		var hint = $((el == this.c_left) ? 'hint_l' : 'hint_r');
		if (starterMode && pageData.hint) {
			hint.down('.content').update(pageData.hint);
			hint.show();
		} else {
			hint.hide();
		}

		var offset = (el == this.c_left) ? 5 : 0;

		$A(pageData.elements).each(function(a) {
			switch (a.type) {
				case 'image':
					var e = $(document.createElement('img'));
					e.src = a.file;
					e.setStyle({left: (a.left*100) + '%', top: (a.top*100) + '%', width: (a.width*100) + '%', height: (a.height*100) + '%', position: 'absolute'}, true);
					el.appendChild(e);
					break;
				case 'place_image':
					if (starterMode) {
						var e = $(document.createElement('div'));
						e.addClassName('place_image')
						e.setStyle({left: (a.left*100) + '%', top: (a.top*100) + '%', width: (a.width*100) + '%', height: (a.height*100) + '%', position: 'absolute'}, true);
						el.appendChild(e);
					}
					break;
				case 'text':
				case 'locked_text':
				case 'text_author':
				case 'text_title':
					var e = $(document.createElement('div'));
					var c = a.content || '';
					if (!a.asIs) {
						c = c.escapeHTML();
						c = c.gsub(/(\r\n|\n\r|\r|\n)/, '<br/>');
						c = c.gsub(/(^|<br\/>)(\s+)/, function(match) {
							var res = match[1];
							for (var i = 0; i < match[2].length; i++) {
								if (match[2][i] == '\t') {
									res += '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
								} else {
									res += '&nbsp;';
								}
							}
							return res;
						});
					}
					e.update(c);
					e.addClassName('text');
					e.setStyle({
						left: (offset + a.left*95) + '%', top: (a.top*100) + '%', width: (a.width*95) + '%', height: (a.height*100) + '%', position: 'absolute',
						fontSize: parseInt(a.fontSize * h) + 'px',
						color: (a.color || '#000000'),
						fontWeight: (a.fontWeight || 'normal'),
						fontStyle: (a.fontStyle || 'normal'),
						textAlign: (a.textAlign || 'left'),
						zIndex: 15
						}, true);
					el.appendChild(e);
					break;
			}
		});
	}
};

var reader = null;

function showReader() {
	reader.doImageReplacements();

	var warning = $('warning');
	if (warning) {
		Event.observe(warning, 'click', function() {
			Effect.Fade($('warning'), {afterFinish: function() { $('warning').hide(); } });
			$('overlay').hide();
		});
	} else {
		Effect.Fade($('overlay'), {afterFinish: function() { $('overlay').hide(); } });
	}
};

function bind() {
	if ('function' != typeof $) {
		window.setTimeout(bind, 100);
		return;
	}
	if (!reader) {
	   reader = new Reader();
	   Event.observe(window, 'load', showReader);
	}
};

Event.onDOMReady(bind);
