
ComicPreloader = Preloader.extend({
	initialize : function(images, start) {
		this.start = start;
		this.parent(images);
	},

	getNext : function(current) {
		if (!$defined(current)) {
			return this.start;
		}
		//if it's zero, then we have backtracked and are done
		if (current == 0 && this.start > 0) {
			return false;	
		}

		//we are backtracking, so go backwards
		if (current < this.start) {
			return current - 1;
		}

		//if it's the last one, we need to start backtracking
		if (current == this.images.length - 1) {
			return this.start - 1;
		}
		//otherwise, return next one
		return current + 1;
	}
});
ComicPreloader.implement(new Events);




ComicPage = new Class({

	options : {
		center : false
	},

	initialize : function(element, page, options) {

		this.setOptions(options);

		this.parent = $(element);
		this.panels = [];
		this.page = page;

		this.element = new Element('div', {
			'class' : 'comic-page',
			title : 'Page ' + page,
			styles : {
				top : (this.options.center ? '50%' : '0')
			}
		}).inject(this.parent);
		this.hide();
	},

	addPanel : function(i, panel) {
		this.panels[i] = panel;
	},

	showing : function() {
		return (this.element.getStyle('visibility') != 'hidden');
	},

	getLast : function() {
		return this.panels.length - ($defined(this.panels[0]) ? 1 : 0);
	},

	checkLoaded : function(l) {
		var l = l ? new Number(l).limit(1, this.getLast()) : this.getLast();
		for (var i = 1; i <= l; i++) {
			if (!this.panels[i].loaded) {
				return false;	
			}
		}
		return true;
	},

	show : function(l) {
		var l = l ? new Number(l).limit(1, this.getLast()) : this.getLast();

		this.element.setStyle('visibility', 'visible');

		if (this.checkLoaded(l)) {
			this.panels[0].hide();
			for (var i = l + 1; i <= this.getLast(); i++) {
				this.panels[i].hide();
			}
			for (var i = 1; i <= l; i++) {
				this.panels[i].show();
			}
			this.waitingFor = false;
		} else {
			this.panels[0].show();
			this.waitingFor = l;
		}
		return l;
	},

	hide : function() {
		this.waitingFor = false;
		for (var i = 0; i < this.panels.length; i++) {
			this.panels[i].hide();
		}
		this.element.setStyle('visibility', 'hidden');
	},

	imageLoaded : function(i, path, s) {
		this.panels[i].loaded = true;
		this.panels[i].setSize(s);
		this.panels[i].loaded = true;
		if (this.showing()) {
			if (this.waitingFor) {
				this.show(this.waitingFor);
			}
		}
	}
});
ComicPage.implement(new Options);



ComicPanel = new Class({

	options : { center : true },

	initialize : function(page, object, options) {
		this.page = page;
		this.parent= $(page.element);
		this.object = object;
		this.loaded = false;
		this.setSize(0, 0);
		this.setOptions(options);
	},

	show : function() {
		if (!this.element) {

			var page = this.parent.getSize().size;
			//store position
			this.position = {
				y : (this.options.center ? (page.y / 2) - (this.size.y / 2) : 0),
				x : (page.x / 2) - (this.size.x / 2)
			};

			this.element = new Element('img', {
				src : this.object.path,
				title : (this.object.description ? ('::' + this.object.description) : ''),
				styles : {
					height : this.size.y + 'px',
					width : this.size.x + 'px',
					left : this.position.x + 'px',
					top : this.position.y + 'px'
				},
				events : {
					click : function() { viewer.go('next_panel'); },
					mouseenter : function(e) { e.stop(); }
				}
			}).inject(this.parent);
			if (this.object.description) {
				if (!this.tooltip) {
					this.tooltip = new Tips(this.element, { fixed : true });
				} else {
					this.tooltip.build(this.element);
				}
			}
		}
	},
	
	hide : function() {
		if (this.element) {
			this.element.remove();
		}
		if (this.tooltip) {
			this.tooltip.end();
		}
		this.element = null;
	},

	setSize : function(s, y) {
		var size = {
			x : $defined(y) ? s : s.x,
			y : $defined(y) ? y : s.y
		};
		if (size.x > 900) {
			size.y = Math.round(900 * size.y / size.x);
			size.x = 900;
		}
		this.size = size;
		var page_size = this.parent.getSize().size;
		if (size.y > page_size.y) {
			this.parent.setStyle('height', size.y + 'px');
		}
		var container_size = this.page.parent.getSize().size;
		if (size.y > container_size.y) {
			this.page.parent.setStyle('height', size.y + 'px');
		}
	}
	
});
ComicPanel.implement(new Options);



ComicViewer = new Class({
	
	current : {
		page : 1,
		panel : 1,
		i : 0
	},

	options : {
		duration : 1000,
		center : true
		/*,
		showtips : true*/
	},

	initialize : function(element, images, options) {

		this.element = $(element);
		this.images = images;

		this.setOptions(options);

		/*
		//do something with tooltips?
		if (this.options.showtips) {
			var tooltip = new Tips(this.element, { fixed: true});
		}
		*/

		//create the page objects
		this.pages = [];
		var start = 0;

		for (var i = 0; i < images.length; i++) {
			var image = images[i];

			//clean up
			image.page = parseInt(image.page);
			image.panel = parseInt(image.panel);
			
			if (image['default'] == 1) {
				this.current = 	{ page : image.page, panel : image.panel, i : i };
				start = i;
			}

			//set up pages
			var page = this.pages[image.page];
			if (!page) {
				page = new ComicPage(this.element, image.page);
				this.pages[image.page] = page;

				//loadImage will be the '0th' panel
				var loadImage = new ComicPanel(page, {path : '/media/tridian/images/spinner3-black.gif', panel : 0 });
				page.addPanel(0, loadImage);
				loadImage.setSize({ x : 36, y : 36});
			}

			page.addPanel(image.panel, new ComicPanel(page, image));
		}

		//start preloading
		this.preloader = new ComicPreloader(this.images, start);
		this.preloader.addEvent('onImageLoad', this.imageLoaded.bind(this));
		this.preloader.addEvent('onImageFail', this.imageFailed.bind(this));

		this.go();
	},

	imageFailed : function(i, src) {
		var image = this.images[i];
		var page = this.pages[image.page];
		image.path = '/administrator/images/cancel.png';
		page.imageLoaded(image.panel, page.path, {x:32,y:32});
	},

	imageLoaded : function(i, src, size) {
		var image = this.images[i];
		var page = this.pages[image.page];
		page.imageLoaded(image.panel, src, size);
	},

	show : function(page, panel) {
		page = new Number(page).limit(1, this.pages.length - 1);
		var last = { page : this.current.page, panel : this.current.panel };		
		if (last.page != page) {
			this.pages[last.page].hide();
		}
		this.current.page = page;
		this.current.panel = this.pages[page].show(panel);
		this.current.i = this.pages[page].panels[this.current.panel].object.i;
	},

	go : function(button) {	

		var i = this.current.i;
		switch (button) {
			case 'first':
				this.show(1, 1);
				break;
			case 'prev_pg':
				if (this.current.page > 1) {
					this.show(this.current.page - 1);
				}
				break;
			case 'prev_panel':
				if (this.current.i > 0) {
					this.show(this.images[i - 1].page, this.images[i - 1].panel);
				}
				break;
			case 'page':
				this.show($('page').value);
				break;
			case 'next_panel':
				if (i + 1 < this.images.length) {
					this.show(this.images[i + 1].page, this.images[i + 1].panel);
				}
				break;
			case 'next_pg':
				this.show(this.current.page + 1);
				break;
			case 'end':
				this.show(this.pages.length);
				break;
			default:
				this.show(this.current.page, this.current.panel);
		}
		var page = $('page');
		if (page) {
			page.value = this.current.page;
		}
	}
});
ComicViewer.implement(new Options);


