/*
	Class: PopImg
	Author: Kory Sharp
	Last Upsub_title: 08/12/08
	Dependencies: prototype.js, scriptaculous.js?load=effects, builder
	
	Usage: 
		Single Image:
			<a href="fullsize_images_path" title="image caption" rel="popimg">text or thumbnail</a>
		Multiple Images:
			<a href="fullsize_images_path" title="image caption" rel="popimg[gallery name]">text or thumbnail</a>
*/

var PopImg = Class.create({
	images: [], // images in current pop set
	loaded: [], // images that have been preloaded
	speed: .3,  // duration for transitions below
	pos: undefined, // index position (from var images) of the current image
	locked: false, // allows animations to finish before attempting another
	scroll_to: true,
	type: '',
	
	initialize: function(type, title, sub_title, scroll_to) {
		// makes sure the keyboard event as well as "this" (PopImg class) are available
		this.key_events = this.key_events.bindAsEventListener(this);
	
		// build out the skeleton of the popimg viewer (overlay and interior)
		var body = $$('body')[0];
		new Insertion.Bottom(body, $(Builder.node('div', { id: 'overlay' })).hide());
		new Insertion.Bottom(body, 
			$(Builder.node('div', { id: 'popimg' }, [
				Builder.node('a', { href: '#', id: 'popimg_close' }),
				Builder.node('div', { id: 'popimg_nav' }, [
					Builder.node('a', { href: '#', id: 'popimg_previous' }),
					Builder.node('a', { href: '#', id: 'popimg_next' })
				]),
				Builder.node('div', { id: 'popimg_image_holder' }, [
					$(Builder.node('img', { id: 'popimg_image' })).hide(),
					Builder.node('div', { id: 'popimg_loading' })
				]),
				Builder.node('p', { id: 'popimg_caption_title' }, title),
				Builder.node('p', { id: 'popimg_caption_sub_title' }, sub_title)
			])).hide()
		);
		this.type = type;
		$('popimg_nav').hide();
		
		if (this.type == "gear") {
			$('popimg').setStyle({ backgroundImage: 'url(/images/popimg/gear_header.jpg)' });
			$('popimg_caption_title').style.left = '125px';
			$('popimg_caption_sub_title').style.left = '125px';
		}
		
		this.scroll_to = scroll_to;
	
		// generate onclick events for the navigational items		
		$('popimg_previous').observe('click', (function(event) { event.stop(); this.switch_image(this.pos - 1); }).bind(this));
		$('popimg_next').observe('click', (function(event) { event.stop(); this.switch_image(this.pos + 1); }).bind(this));
		$('popimg_close').observe('click', (function(event) { event.stop(); this.close(); }).bind(this));
		$('overlay').observe('click', (function(event) { event.stop(); this.close(); }).bind(this));
		
		// read the click event for any link containing popimg
		document.observe('click', (function(event){
            var img = event.findElement('a[rel^=popimg]');
            if (img) {
                event.stop();
                this.open(img);
            }
        }).bind(this));
	},
	open: function(img) {
		// set the height of the overlay
		$('overlay').setStyle({ height: this.get_window_height() + "px" });
		
		// set the left position of the popimg viewer
		$('popimg').setStyle({ left: (document.viewport.getWidth() / 2) - ($('popimg').getWidth() / 2) + 'px' });
		
		if (!this.scroll_to) $('popimg').setStyle({ top: document.viewport.getScrollOffsets()[1] + 'px' });
		
		// fade in the overlay and the popimg container
		new Effect.Appear('overlay', { 
			from: 0, 
			to: .84, 
			duration: this.speed,
			afterFinish: (function() {
				new Effect.Appear('popimg', { 
					from: 0, 
					to: 1, 
					duration: this.speed,
					afterFinish: (function() {
						this.find_images(img);
						this.enable_keyboard();
					}).bind(this)
				});
				if (this.scroll_to) new Effect.ScrollTo('popimg');
			}).bind(this)
		});
	},
	close: function() {
		$('popimg').hide();
		$('popimg_image').hide();
		this.disable_keyboard();
		new Effect.Fade('overlay', { duration: this.speed });	
	},
	find_images: function(img) {
		this.images = [];
		this.loaded = [];
		this.pos = 0;
		if (img.readAttribute('rel') == 'popimg') {
			this.images.push([img.readAttribute('href'), img.readAttribute('title')]);
			this.loaded.push(false);
		} else {
			$$('a[href][rel="' + img.readAttribute('rel') + '"]').uniq().each((function(img) {
				this.images.push([img.readAttribute('href'), img.readAttribute('title')]);
				this.loaded.push(false);
			}).bind(this));
			for (var i = 0; i < this.images.length; i++ ) {
				if (this.images[i][0] == img.readAttribute('href')) {
					this.pos = i;
					break;
				}
			}
		}
		
		if (this.images.length < 2 || this.type == "gear") $('popimg_nav').hide();
		else $('popimg_nav').show();
		
		this.switch_image(this.pos);
	},
	switch_image: function(pos) {
		if (this.images.length > 1 || !$('popimg_image').visible()) {
			this.locked = true;
			// make sure pos is in range
			if (pos < 0) pos = this.images.length - 1;
			else if (pos >= this.images.length) pos = 0;
			this.pos = pos; 
			
			// pull title/price and display
			if (this.type == "gear") {
				$$('#gear_list .left img').each((function(x) {
					if (x.up('a') && x.up('a').readAttribute('href') == this.images[this.pos][0]) {
						$('popimg_caption_title').update(x.up('.product').down('.title').innerHTML);
						$('popimg_caption_sub_title').update("Price: " + x.up('.product').down('.price').innerHTML);
					}
				}).bind(this));
			}
						
			new Effect.Fade('popimg_image', {
				duration: this.speed,
				afterFinish: (function() {
				
					if (!this.loaded[this.pos]) $('popimg_loading').show();
					var preload = new Image();
					preload.onload = (function(image) {
						this.loaded[this.pos] = true;
						$('popimg_loading').hide();
						this.preload();
						
						$('popimg_image').setStyle({
							marginTop: Math.floor(($('popimg_image_holder').getHeight() - image.height - 10) / 2) + 'px',
							marginLeft: Math.floor(($('popimg_image_holder').getWidth() - image.width - 10) / 2) + 'px'
						});
						
						$('popimg_image').src = this.images[this.pos][0];
						new Effect.Appear('popimg_image', { 
							duration: this.speed,
							afterFinish: (function() {
								this.locked = false
							}).bind(this)
						});
					}).bind(this, preload);
					preload.src = this.images[this.pos][0];
				}).bind(this)
			});
		}
	},
	preload: function() {
		// preload the previous and next images
		var previous = (this.pos > 0 && !this.loaded[this.pos - 1]) ? this.pos - 1 : this.images.length - 1;
		var back_preload = new Image();
		back_preload.onload = (function() { this.loaded[previous] = true; }).bind(this);
		back_preload.src = this.images[previous][0];
		
		var next = (this.pos < (this.images.length - 1) && !this.loaded[this.pos + 1]) ? this.pos + 1 : 0;
		var next_preload = new Image();
		next_preload.onload = (function() { this.loaded[next] = true; }).bind(this);
		next_preload.src = this.images[next][0];
	},
	enable_keyboard: function() { Event.observe(document, "keydown", this.key_events); },
	disable_keyboard: function() { Event.stopObserving(document, "keydown", this.key_events); },
	key_events: function(event) {
		switch (event.keyCode) {
			// 'b' or left arrow
			case 37:
			case 66:
				if (!this.locked) this.switch_image(this.pos - 1);
				break;
			// 'n' or right arrow
			case 39:
			case 78:
				if (!this.locked) this.switch_image(this.pos + 1);
				break;
			// esc, 'x', or 'c'
			case 27:
			case 67:
			case 88:
				this.close();
				break;
			default:
				break;
		}
	},
	get_window_height: function() {
		// retrieve the height of the document including scrollable area
		var document_height, window_height;
		
		if (window.innerHeight && window.scrollMaxY) document_height = window.innerHeight + window.scrollMaxY;
		else if (document.body.scrollHeight > document.body.offsetHeight) document_height = document.body.scrollHeight;
		else document_height = document.body.offsetHeight;
		
		if (self.innerHeight) window_height = self.innerHeight;
		else if (document.documentElement && document.documentElement.clientHeight) window_height = document.documentElement.clientHeight;
		else if (document.body) window_height = document.body.clientHeight;
		
		return (document_height < window_height) ? window_height : document_height;
	}
});