var Flibt = Class.create();

Flibt.prototype = {
	// user settable
	container_id : null,
	image_list_json_url : null,
	comments_service_url : null,
	thumb_container_class : '',
	full_container_class : '',
	thumb_controls_class : '',
	album_controls_class : '',
	slideshow_controls_class : '',
	loader_image_class : '',	
	main_loader_class : '',
	album_base_fontsize : 10,
	album_selected_fontsize : 13,
	slideshow_interval : 4000,
	minimum_slideshow_interval : 2000,
	current_album : null,
		
	// private
	thumbs_loaded : false,
	thumb_backdrop : null,
	thumb_container : null,
	thumb_controls_container : null,
	album_controls_container : null,
	full_container : null,
	tracked_x : null,
	tracked_y : null,
	slider_timer : null,
	thumb_slider_fx : null,
	loader_image : null,
	current_image : null,
	main_loader : null,
	currently_selected_thumb : null,
	slideshow_timer : null,
	slideshow_active : null,
	
	initialize : function(params)	{
		Object.extend(this, params);
		
		$(this.container_id).style.width = '100%';
		$(this.container_id).style.overflow = 'hidden';
		
		this.show_main_loader();
		
		new Ajax.Request(
			this.image_list_json_url, 
			{
				method: 'post', 
				parameters: '', 
				onComplete: this.activate.bind(this)
			}
		);
	},
	
	show_main_loader : function()	{
		for(var i = 0; i < document.body.childNodes.length; i++)	{
			if(document.body.childNodes[i].tagName)
				document.body.childNodes[i].style.visibility = 'hidden';
		}
		
		this.loader = document.createElement('div');
		this.loader.styleClass = this.main_loader_class;
		this.loader.className = this.main_loader_class;
		
		var loader_img = document.createElement('img');
		loader_img.src = 'images/full_loader.gif';
		this.loader.appendChild(loader_img);
		
		/*
		var loader_text = document.createElement('span');
		loader_text.innerHTML = ' Loading...';
		this.loader.appendChild(loader_text);
		*/
		
		document.body.appendChild(this.loader);
	},

	hide_main_loader : function()	{
		document.body.removeChild(this.loader);
		
		for(var i = 0; i < document.body.childNodes.length; i++)	{
			if(document.body.childNodes[i].tagName)
				document.body.childNodes[i].style.visibility = 'visible';
		}
	},
		
	activate : function(ajax)	{
		var image_list = eval('(' + ajax.responseText + ')');	
		
		// create thumb container
		this.thumb_container = document.createElement('div');
		this.thumb_container.styleClass = this.thumb_container_class;
		this.thumb_container.className = this.thumb_container_class;
		this.thumb_container.style.overflow = 'auto';
		this.thumb_container.style.position = 'relative';
		this.thumb_container.style.left = '0px';
		
		this.thumb_backdrop = document.createElement('div');
		$(this.container_id).appendChild(this.thumb_backdrop);
		this.thumb_backdrop.style.width = $(this.container_id).scrollWidth + 'px';
		this.thumb_backdrop.style.overflow = 'hidden';		
		this.thumb_backdrop.styleClass = 'hidden_overflow';		
		this.thumb_backdrop.className = 'hidden_overflow';		
		this.thumb_backdrop.appendChild(this.thumb_container);
		
		// style the top bar
		if(this.thumb_container.getStyle)
			this.thumb_backdrop.style.backgroundColor = this.thumb_container.getStyle('backgroundColor');
		
		var albums = '';
		// populate thumb container
		for(var i = 0; i < image_list.length; i++)	{
			var image_container = document.createElement('div');
			image_container.style.visibility = 'hidden';
			// image_container.hider_fx = new Fx.Width(image_container, {duration: 500, transition: Fx.Transitions.circInOut});			
			this.thumb_container.appendChild(image_container);
			
			var image = document.createElement('img');
			image.src = 'services/thumb_image.php?file=' + image_list[i];
			image.file = image_list[i];
			image.album = image.file.split('/')[0];
			Event.observe(image, 'click', this.load_full_image.bindAsEventListener(this), false);
			
			// onmouseover effects for the thumbnails
			/*
			image.focus_fx = new Fx.Styles(image, {duration: 250, transition: Fx.Transitions.sineOut, onComplete: (function()	{
				var target_opacity;
				target_opacity = this.getStyle('opacity') == 0.5 ? 1 : 0.5;
				
				this.focus_fx.custom({
					opacity : [this.getStyle('opacity'), target_opacity]
				});
			}).bind(image)});
			Event.observe(image, 'mouseover', function(evt)	{
				var element = Event.element(evt);
				
				element.focus_fx.custom({
					opacity : [element.getStyle('opacity'), .5]
				});
			}, false);
			Event.observe(image, 'mouseout', function(evt)	{
				var element = Event.element(evt);
				
				element.focus_fx.clearTimer();
				element.focus_fx.setStyle(element, 'opacity', 1);
			}, false);
			*/
			
			// to compile a list of all the albums we have
			if(albums.indexOf(image.album) == -1)
				albums += image.album + '[-]';
						
			image_container.appendChild(image);
		}
		
		this.albums = albums.split('[-]');
		this.albums.length--;
		
		this.complete_thumbs();
	},
	
	handle_resize : function()	{
		this.set_album_filter({ target : { innerHTML : this.current_album }, srcElement : { innerHTML : this.current_album } });
		this.thumb_backdrop.style.width = $(this.container_id).scrollWidth + 'px';
	},
	
	complete_thumbs : function()	{
		// oops - did this get called a second time by mistake?
		if(this.thumbs_loaded)
			return;
		
		// verify that all the thumbnails are loaded
		for(var i = 0; i < this.thumb_container.childNodes.length; i++)	{
			if(!this.is_image_loaded(this.thumb_container.childNodes[i].firstChild))	{
				window.setTimeout(this.complete_thumbs.bind(this), 500);
				return;	
			}
		}
		
		// all thumbs have been loaded
		this.thumbs_loaded = true;

		// set the width of the thumb scroller
		this.fix_thumb_container_width();		
		
		// make hidden thumbs visible		
		for(var i = 0; i < this.thumb_container.childNodes.length; i++)
			this.thumb_container.childNodes[i].style.visibility = 'visible';

		// add the fullsize image container
		this.full_container = document.createElement('div');
		this.full_container.className = this.full_container_class;
		this.full_container.styleClass = this.full_container_class;
		this.full_container.style.position = 'relative';
		$(this.container_id).appendChild(this.full_container);

		// load the first image
		var current_image = document.createElement('img');
		this.full_container.appendChild(current_image);
		current_image.src = 'services/full_image.php?file=' + this.thumb_container.childNodes[0].firstChild.file;		
		current_image.fader_fx = new Fx.Styles(current_image, {duration: 500, transition: Fx.Transitions.sineOut});
		this.current_image = current_image;
		this.currently_selected_thumb = this.thumb_container.childNodes[0].firstChild;
		
		// add thumbnail navigation controls
		this.make_thumbs_navigable();
		
		// add slideshow controls
		this.make_slideshow_controls();
		
		// resize the thumbs div when the window width changes
		Event.observe(window, 'resize', this.handle_resize.bind(this), false);
		
		// get rid of the big loading box
		this.hide_main_loader();
		
		// set the default album view
		this.set_album_filter({ target : { innerHTML : this.current_album }, srcElement : { innerHTML : this.current_album } });
	},
	
	make_slideshow_controls : function()	{
		this.slideshow_controls_container = document.createElement('div');
		this.slideshow_controls_container.styleClass = this.slideshow_controls_class;
		this.slideshow_controls_container.className = this.slideshow_controls_class;
		$(this.container_id).insertBefore(this.slideshow_controls_container, this.full_container);

		var slideshow_slower_link = document.createElement('a');
		slideshow_slower_link.innerHTML = 'slower';
		slideshow_slower_link.fx = new Fx.Styles(slideshow_slower_link, {duration: 1000, transition: Fx.Transitions.sineOut});
		slideshow_slower_link.fx.setStyle(slideshow_slower_link, 'opacity', 0);
		Event.observe(slideshow_slower_link, 'click', (function(evt)	{
			this.change_slideshow_speed(1000);
			
			// show them where they're at now
			var element = Event.element(evt);
			element.innerHTML = this.slideshow_interval / 1000 + ' seconds';
			window.setTimeout((function()	{
				this.innerHTML = 'slower';
			}).bind(element), 750);
		}).bindAsEventListener(this), false); 
				
		var slideshow_start_link = document.createElement('a');
		slideshow_start_link.innerHTML = 'start slideshow';
		Event.observe(slideshow_start_link, 'click', this.toggle_slideshow.bind(this), false);

		var slideshow_faster_link = document.createElement('a');
		slideshow_faster_link.innerHTML = 'faster';
		slideshow_faster_link.fx = new Fx.Styles(slideshow_faster_link, {duration: 1000, transition: Fx.Transitions.sineOut});
		slideshow_faster_link.fx.setStyle(slideshow_faster_link, 'opacity', 0);
		Event.observe(slideshow_faster_link, 'click', (function(evt)	{
			this.change_slideshow_speed(-1000);
			
			// show them where they're at now
			var element = Event.element(evt);
			element.innerHTML = this.slideshow_interval / 1000 + ' seconds';
			window.setTimeout((function()	{
				this.innerHTML = 'faster';
			}).bind(element), 750);
		}).bindAsEventListener(this), false); 
		
		this.slideshow_controls_container.appendChild(slideshow_slower_link);
		this.slideshow_controls_container.appendChild(slideshow_start_link);
		this.slideshow_controls_container.appendChild(slideshow_faster_link);
	},
	
	toggle_slideshow : function()	{
		var element = this.slideshow_controls_container.childNodes[1];
		
		if(this.slideshow_timer)	{
			// stop it
			this.slideshow_active = false;
			this.slideshow_timer = window.clearTimeout(this.slideshow_timer);
			
			// hide the faster/slower controls
			this.slideshow_controls_container.lastChild.fx.custom({
				'opacity' : [1, 0]	
			});
			this.slideshow_controls_container.firstChild.fx.custom({
				'opacity' : [1, 0]	
			});
			
			// redo the link
			element.innerHTML = 'start slideshow';
		} else	{
			// start it
			this.slideshow_timer = window.setTimeout(this.advance_slideshow.bind(this), this.slideshow_interval);
			this.slideshow_active = true;
			
			// show the faster/slower controls
			this.slideshow_controls_container.lastChild.fx.custom({
				'opacity' : [0, 1]	
			});
			this.slideshow_controls_container.firstChild.fx.custom({
				'opacity' : [0, 1]	
			});
			
			// redo the link
			element.innerHTML = 'stop slideshow';
		}
	},
	
	change_slideshow_speed : function(increment)	{
		this.slideshow_interval = Math.max(this.minimum_slideshow_interval, this.slideshow_interval + increment);
	},

	advance_slideshow : function()	{
		var next_image = null;
		var first_image = null;
		
		for(var i = 0; i < this.thumb_container.childNodes.length; i++)	{
			var check_image = this.thumb_container.childNodes[i].firstChild;
			
			// mark and retain the first image of the album in case we need to cycle
			if(
				!first_image && 
				(check_image.album == this.current_album ||	this.current_album == 'show all')
			)	{
				first_image = check_image;
			}
			
			// mark and retain the next image in the sequence
			if(
				this.currently_selected_thumb == check_image &&
				check_image.parentNode.nextSibling &&
				(
					check_image.parentNode.nextSibling.firstChild.album == this.current_album ||
					this.current_album == 'show all'
				)
			)	{
				next_image = check_image.parentNode.nextSibling.firstChild;
			}
		}
		
		// if we don't have a next image, go back to the initial image
		next_image = next_image || first_image;
		
		this.load_full_image(next_image);
	},
	
	fix_thumb_container_width : function()	{
		// this function resizes the thumb container so it takes up the whole window
		var desired_width = 0;
		for(var i = 0; i < this.thumb_container.childNodes.length; i++)	{
			desired_width += this.thumb_container.childNodes[i].offsetWidth;
		}
		this.thumb_container.style.width = desired_width + 'px';
		this.thumb_container.style.width = desired_width + 'px';
		
		// reset it to 0
		if(this.thumb_slider_fx)	{
			this.thumb_slider_fx.clearTimer();
			this.thumb_slider_fx.custom({
				left : [this.thumb_container.offsetLeft, 0]
			});
		}
	},
	
	make_thumbs_navigable : function()	{
		this.thumb_slider_fx = new Fx.Styles(this.thumb_container, {duration: 1500, transition: Fx.Transitions.backOut});
		
		this.thumb_controls_container = document.createElement('div');
		this.thumb_controls_container.styleClass = this.thumb_controls_class;
		this.thumb_controls_container.className = this.thumb_controls_class;
		$(this.container_id).insertBefore(this.thumb_controls_container, this.full_container);
		
		// quick backward
		var fast_left_nav = document.createElement('img');
		fast_left_nav.src = 'images/larrlarr.gif';
		this.thumb_controls_container.appendChild(fast_left_nav);
		Event.observe(fast_left_nav, 'click', (function()	{
			this.thumb_slider_fx.clearTimer();
			this.thumb_slider_fx.custom({
				left : [this.thumb_container.offsetLeft, Math.min(0, this.thumb_container.offsetLeft + 2.75 * $(this.container_id).offsetWidth)]
			});
		}).bind(this), false);
		
		// backward	
		var left_nav = document.createElement('img');
		left_nav.src = 'images/larr.gif';
		this.thumb_controls_container.appendChild(left_nav);
		Event.observe(left_nav, 'click', (function()	{
			this.thumb_slider_fx.clearTimer();
			this.thumb_slider_fx.custom({
				left : [this.thumb_container.offsetLeft, Math.min(0, this.thumb_container.offsetLeft + 0.75 * $(this.container_id).offsetWidth)]
			});
		}).bind(this), false);
		
		// loader
		this.loader_image  = document.createElement('img');
		this.loader_image.styleClass = this.loader_image_class;
		this.loader_image.className = this.loader_image_class;
		this.loader_image.src = 'images/full_loader.gif';
		this.thumb_controls_container.appendChild(this.loader_image);

		// forward
		var right_nav = document.createElement('img');
		right_nav.src = 'images/rarr.gif';
		this.thumb_controls_container.appendChild(right_nav);
		Event.observe(right_nav, 'click', (function()	{
			this.thumb_slider_fx.clearTimer();
			this.thumb_slider_fx.custom({
				left : [this.thumb_container.offsetLeft, Math.max($(this.container_id).offsetWidth - this.thumb_container.offsetWidth, this.thumb_container.offsetLeft - 0.75 * $(this.container_id).offsetWidth)]
			});
		}).bind(this), false);
		
		// quick forward
		var fast_right_nav = document.createElement('img');
		fast_right_nav.src = 'images/rarrrarr.gif';
		this.thumb_controls_container.appendChild(fast_right_nav);
		Event.observe(fast_right_nav, 'click', (function()	{
			this.thumb_slider_fx.clearTimer();
			this.thumb_slider_fx.custom({
				left : [this.thumb_container.offsetLeft, Math.max($(this.container_id).offsetWidth - this.thumb_container.offsetWidth, this.thumb_container.offsetLeft - 2.75 * $(this.container_id).offsetWidth)]
			});
		}).bind(this), false);
		
		// album controls	
		this.album_controls_container = document.createElement('div');
		this.album_controls_container.styleClass = this.album_controls_class;
		this.album_controls_container.className = this.album_controls_class;
		$(this.container_id).insertBefore(this.album_controls_container, this.full_container);
		
		// individual album links
		for(var i = 0; i < this.albums.length; i++)	{
			var album_link = document.createElement('a');
			album_link.innerHTML = this.albums[i];
			Event.observe(album_link, 'click', this.set_album_filter.bindAsEventListener(this), false);
			album_link.color_fx = new Fx.Color(album_link, 'color', {duration: 1000, transtion: Fx.Transitions.sineOut});
			album_link.base_color = album_link.style.color = album_link.getStyle('color');
			this.album_controls_container.appendChild(album_link);
		}
		
		// all pictures link
		var all_link = document.createElement('a');
		all_link.innerHTML = 'show all';
		all_link.color_fx = new Fx.Color(all_link, 'color', {duration: 1000, transtion: Fx.Transitions.sineOut});
		all_link.base_color = all_link.style.color = all_link.getStyle('color');
		Event.observe(all_link, 'click', this.set_album_filter.bindAsEventListener(this), false);	
		this.album_controls_container.appendChild(all_link);
	},

	set_album_filter : function(evt)	{
		var album_link = Event.element(evt);
		this.current_album = album_link.innerHTML || this.albums[0];
		
		// this try catch block does the album selection focus effect
		try	{
			for(var i = 0; i < this.album_controls_container.childNodes.length; i++)	{
				var link_element = this.album_controls_container.childNodes[i];
				link_element.color_fx.clearTimer();
				
				if(link_element.innerHTML == this.current_album)	{
					link_element.color_fx.custom(link_element.getStyle('color').rgbToHex(), 'aaaa99');
				}
				else	{
					if(link_element.base_color != link_element.getStyle('color'))	{
						link_element.color_fx.custom(link_element.getStyle('color').rgbToHex(), '000000');
					}
				}
			}
		} catch(e)	{
			// ie sucks. move along.	
		}
		
		// hide all the ones that should be non-shown, show all the ones that should be shown
		for(var i = 0; i < this.thumb_container.childNodes.length; i++)	{
			this.thumb_container.childNodes[i].style.display = (this.current_album == 'show all' || this.current_album == this.thumb_container.childNodes[i].firstChild.album) ? 'inline' : 'none';
		}

		// reset the thumb slider width
		this.fix_thumb_container_width();
		
		// stop the slideshow if one is happening
		if(this.slideshow_active)
			this.toggle_slideshow();
	},
		
	is_image_loaded : function(img)	{
	    // During the onload event, IE correctly identifies any images
	    // that weren't downloaded as not complete. Others should too.
	    // Gecko-based browsers act like NS4 in that they report this
	    // incorrectly: they always return true.
	    if (!img.complete) {
	        return false;
	    }
	
	    // However, they do have two very useful properties: naturalWidth
	    // and naturalHeight. These give the true size of the image. If
	    // it failed to load, either of these should be zero.
	    if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) {
	        return false;
	    }
	
	    // No other way of checking: assume it's ok.
	    return true;
	},
	
	load_full_image : function(param)	{
		// two points of entry - slideshow periodical function, or click on thumbnail
		var clicked_image;
		
		if(param.file)	{
			// slideshow entry	
			clicked_image = param;
		}
		else	{
			// image click entry	
			clicked_image = Event.element(param);
			// stop the slideshow if one is happening
			if(this.slideshow_active)
				this.toggle_slideshow();
		}
		
		this.currently_selected_thumb = clicked_image;
		
		// show we're working
		this.loader_image.style.visibility = 'visible';
		
		// keep track of the old guy
		this.old_image = this.full_container.firstChild;
		
		// fade away what's there
		this.old_image.fader_fx.clearTimer();
		this.old_image.fader_fx.custom({
			'opacity' : [1, 0]
		});
		
		// start loading the new image
		var new_image = document.createElement('img');
		new_image.style.width = 0 + 'px';
		new_image.fader_fx = new Fx.Styles(new_image, {duration: 500, transition: Fx.Transitions.sineOut});
		new_image.fader_fx.setStyle(new_image, 'opacity', 0);
		this.full_container.insertBefore(new_image, this.old_image);
		new_image.src = 'services/full_image.php?file=' + clicked_image.file || clicked_image.firstChild.file;
		
		// keep track of the new guy
		this.current_image = new_image;
		
		// get comments for this guy
		this.get_comments(clicked_image.file);
		
		// need to do this because IE doesn't like image.onload for cached images
		window.setTimeout(this.full_image_loader_monitor.bind(this), 100);
	},
	
	get_comments : function(file)	{
		return;
		
		new Ajax.Request(
			this.comments_service_url,
			{
				method: 'post', 
				parameters: 'action=get&file=' + file, 
				onComplete: this.process_comments.bind(this)
			}
		);
	},
	
	process_comments : function(ajax)	{
		alert(ajax.responseText);
	},
	
	full_image_loader_monitor : function()	{
		if(this.is_image_loaded(this.current_image))	{
			this.current_image.style.width = '';
			this.full_container.removeChild(this.old_image);

			// fade in the newly loaded image
			this.current_image.fader_fx.clearTimer();
			this.current_image.fader_fx.custom({
				'opacity' : [0, 1]
			});

			// we're done, so hide the loader animation
			this.loader_image.style.visibility = 'hidden';
			
			// if a slideshow is going, trigger the timer for the next image
			if(this.slideshow_active)
				this.slideshow_timer = window.setTimeout(this.advance_slideshow.bind(this), this.slideshow_interval);
		}	else	{
			window.setTimeout(this.full_image_loader_monitor.bind(this), 100);
		}
	}
};