var OCGallery = Class.create();
OCGallery.prototype =
{
	initialize : function ()
	{
		this.onClickGalleryCallback = this.onClickGallery.bindAsEventListener(this);
		// find all the galleries
		var divs = $('left').getElementsByTagName('div');
		for (var i = 0; i < divs.length; i++)
		{
			if (divs[i].className == 'art-galleries')
			{
				this.galleries_div = divs[i];
			}
		}
		if (!this.galleries_div)
		{
			return;
		}
		this.galleries_list = this.galleries_div.getElementsByTagName('ul')[0];
		this.galleries_list_items = this.galleries_list.getElementsByTagName('li');
		this.galleries_links = new Array();
		for (var i = 0; i < this.galleries_list_items.length; i++)
		{
			this.galleries_links.push(this.galleries_list_items[i].getElementsByTagName('a')[0]);
		}
		this.gallery_slugs = new Array();
    	var current_cookie = this.getCurrentCookie();
    	var current_slug = false;
		for (var i = 0; i < this.galleries_links.length; i++)
		{
			// link is "/art/[gallery name].html"
			var link = this.galleries_links[i].getAttribute('href');
			var html_loc = link.indexOf('.html');
			var name_loc = link.indexOf('/art/')+5;
			var name = link.substr(name_loc, html_loc-name_loc);
			this.galleries_links[i].gallery_slug = name;
			this.gallery_slugs.push(name);
			if (name == current_cookie)
			{
				current_slug = name;
			}
		}
		
		// locate or create the art-works list
		var art_works_divs = document.getElementsByClassName('art-works');
		if (!art_works_divs.length)
		{
			this.art_works_div = document.createElement('div');
			this.art_works_div.className = 'art-works';
			var temp_ul = document.createElement('ul');
			this.art_works_div.appendChild(temp_ul);
			$('right').appendChild(this.art_works_div);
		}
		else
		{
			this.art_works_div = art_works_divs[0];
		}
		this.art_works_list = this.art_works_div.getElementsByTagName('ul')[0];
		
		var art_works_clear = document.createElement('div');
		art_works_clear.className = 'clearance';
		art_works_clear.appendChild(document.createElement('br'));
		this.art_works_div.appendChild(art_works_clear);
		
		if (navigator.userAgent.indexOf('MSIE') != -1)
		{
			// have to do this for MSIE or the effect won't work, for some reason
			Element.setStyle(this.art_works_div, { "zoom" : "1" });
		}
		this.list_effect = new fx.Opacity(this.art_works_div,
    	{
    		duration: 500
    	});
    	
    	// create the activity indicator
    	this.activity = document.createElement('img');
    	this.activity.setAttribute('src', '/js/activity.gif');
    	Element.setStyle(this.activity,
    		{
    			"position" : "absolute",
    			"right" : "0.33em",
    			"top" : "0.33em",
    			"display" : "none"
    		});
    	Element.setStyle(this.galleries_div, { "position" : "relative" });
    	this.galleries_div.appendChild(this.activity);
    	
    	// show previously visible gallery
		if (current_slug)
		{
			this.startActivity();
			this.list_effect.hide();
			this.url = '/art/'+current_slug+'.xml';
			this.showing_gallery = current_slug;
			this.sendGalleryRequest();
		}
		
		// attach behaviors to gallery links
		for (var i = 0; i < this.galleries_links.length; i++)
		{
			Event.observe(this.galleries_links[i], 'click', this.onClickGalleryCallback);
			this.galleries_links[i].onclick = function() { return false; } // for Safari
		}
	},
    
    startActivity : function ()
    {
    	if (!this.activity_stack)
    	{
    		this.activity_stack = new Array();
    	}
    	this.activity_stack.push(1);
    	Element.setStyle(this.activity, { "display" : "block" });
    },
    
    stopActivity : function ()
    {
    	this.activity_stack.pop();
    	if (this.activity_stack.length == 0)
    	{
    		Element.setStyle(this.activity, { "display" : "none" });
    	}
    	else
    	{
    		Element.setStyle(this.activity, { "display" : "block" });
    	}
    },
    
    onGalleryOpaque : function ()
    {
    	this.list_effect.options.onComplete = null;
    	this.stopActivity();
    	if (this.next_switch && this.next_switch != this.showing_gallery)
    	{
    		var next_switch = this.next_switch;
    		this.next_switch = null;
    		this.onClickGallery(next_switch);
    	}
    	else
    	{
    		this.next_switch = null;
    	}
    },
	
	onClickGallery : function (e)
	{
		var gallery_slug;
		if (typeof e != 'string')
		{
			var link = Event.element(e);
			if (!link.gallery_slug)
			{
				return;
			}
			gallery_slug = link.gallery_slug;
		}
		else
		{
			gallery_slug = e;
		}
		if (this.activity_stack && this.activity_stack.length != 0)
		{
			this.next_switch = gallery_slug;
			Event.stop(e);
			return;
		}
		Event.stop(e);
		this.startActivity();
		this.setCurrentCookie(gallery_slug);
		this.url = '/art/'+gallery_slug+'.xml';
		this.showing_gallery = gallery_slug;
		if (!this.sendGalleryRequestCallback)
		{
			this.sendGalleryRequestCallback = this.sendGalleryRequest.bind(this);
		}
		this.list_effect.options.onComplete = this.sendGalleryRequestCallback;
		this.list_effect.toggle();
	},
	
	sendGalleryRequest : function ()
	{
		this.list_effect.options.onComplete = '';
		if (!this.writeGalleryCallback)
		{
			this.writeGalleryCallback = this.writeGallery.bind(this);
			this.failGalleryCallback = this.failGallery.bind(this);
		}
		new Ajax.Request(
			this.url,
			{
				method : 'get',
				onSuccess : this.writeGalleryCallback,
				onFailure : this.failGalleryCallback
			});
	},
	
	failGallery : function (request)
	{
		this.stopActivity();
		var error = 'failure! ('+request.statusText+') ';
		alert(error);
	},
	
	writeGallery : function (request)
	{
		//this.stopActivity();
		if (!request.responseXML)
		{
			return;
		}
		if (!this.onClickWorkCallback)
		{
			this.onClickWorkCallback = this.onClickWork.bindAsEventListener(this);
		}
		var doc = request.responseXML;
		var works = doc.getElementsByTagName('works')[0];
		var gallery_slug = works.getAttribute('gallery_slug');
		var gallery_name = works.getAttribute('gallery');
		// clear current art works
		this.art_works_list.innerHTML = '';
		var works_arr = doc.getElementsByTagName('work');
		this.works_loaded = 0;
		this.works_to_load = works_arr.length;
		for (var i = 0; i < works_arr.length; i++)
		{
			var work = works_arr[i];
			var work_li = document.createElement('li');
			var work_link = document.createElement('a');
			work_link.work_dims = 
				{
					width : parseInt(work.getAttribute('width')),
					height : parseInt(work.getAttribute('height'))
				};
			work_link.work_title = work.getAttribute('title');
			work_link.setAttribute('href', work.getAttribute('href')+'.html');
			work_link.setAttribute('title', work.getAttribute('title'));
			/*var work_image = new Image();
			Event.observe(work_image, 'load', function ()
				{
					this.works_loaded = this.works_loaded + 1;
				}.bind(this));
			work_image.src = work.getAttribute('thumbnail_url');*/
			
			var work_img = document.createElement('img');
			work_img.setAttribute('src', work.getAttribute('thumbnail_url'));
			work_img.setAttribute('alt', work.getAttribute('title'));
			work_link.appendChild(work_img);
			work_li.appendChild(work_link);
			Event.observe(work_link, 'click', this.onClickWorkCallback);
			work_link.onclick = function () { return false; } // for Safari
			this.art_works_list.appendChild(work_li);
		}
					
		if (!this.checkListLoadedCallback)
		{
			this.checkListLoadedCallback = this.checkListLoaded.bind(this);
		}
		this.checkListLoadedCallback();
	},
	
	checkListLoaded : function ()
	{
		if (this.times_checked == null)
		{
			this.times_checked = 1;
		}
		else
		{
			this.times_checked = this.times_checked+1;
		}
		var all_loaded = true;
		var imgs = this.art_works_list.getElementsByTagName('img');
		for (var i = 0; i < imgs.length; i++)
		{
			var image = imgs[i];
			if (!image.offsetHeight)
			{
				all_loaded = false;
			}
		}
		/*
		var all_loaded = false;
		if (this.works_loaded == this.works_to_load)
		{
			all_loaded = true;
		}
		*/
		if (all_loaded || this.times_checked == 12)
		{
			if (!this.onGalleryOpaqueCallback)
			{
				this.onGalleryOpaqueCallback = this.onGalleryOpaque.bind(this);
			}
			this.list_effect.options.onComplete = this.onGalleryOpaqueCallback;
			this.list_effect.clearTimer();
			this.list_effect.custom(0.0, 1.0);
			this.times_checked = null;
		}
		else
		{
			window.setTimeout(this.checkListLoadedCallback, 250);
		}
	},
	
	onClickWork : function (e)
	{
		var link = Event.findElement(e, 'a');
		// figure out xml url of the work
		var href = link.getAttribute('href');
		var start = href.indexOf('/art/');
		var end = href.indexOf('.html', start);
		if (start == -1 || end == -1)
		{
			return;
		}
		Event.stop(e);
		var url = href.substr(start, end-start)+'.xml';
		if (!this.writeWorkCallback)
		{
			this.writeWorkCallback = this.writeWork.bind(this);
			this.failWorkCallback = this.failWork.bind(this);
		}
		if (!this.work_details_div)
		{
			this.work_details_div = document.createElement('div');
			this.work_details_div.setAttribute('id', 'js_art_gallery_details');
			Element.setStyle(this.work_details_div,
				{
					"position" : "absolute",
					"left" : "0px",
					"top" : "0px",
					"display" : "none",
					"background-color" : "white",
					"z-index" : "1011"
				});
			document.body.appendChild(this.work_details_div);
			
			this.work_activity = document.createElement('img');
			this.work_activity.setAttribute('id', 'js_art_gallery_work_activity');
			this.work_activity.setAttribute('src', '/js/activity.gif');
			Element.setStyle(this.work_activity,
				{
					"position" : "absolute",
					"left" : "50%",
					"top" : "50%",
					"margin-left" : "-8px",
					"margin-top" : "-8px",
					"display" : "none"
				});
			this.work_details_div.appendChild(this.work_activity);
			
			this.work_info_div = document.createElement('div');
			this.work_info_div.setAttribute('id', 'js_art_gallery_work_info');
			Element.setStyle(this.work_info_div,
				{
					"position" : "absolute",
					"top" : "0px",
					"right" : "0px",
					"width" : "150px",
					"z-index" : "1011",
					"display" : "none"
				});
			document.body.appendChild(this.work_info_div);
			/*Event.observe(this.work_info_div, 'mouseover', function (e)
				{
					Event.stop(e);
					this.over_info = true;
				}.bindAsEventListener(this));*/
			//this.work_details_div.appendChild(this.work_info_div);
		}
		if (!this.work_img)
		{
			this.work_img = document.createElement('img');
			Element.setStyle(this.work_img,
				{
					"display" : "none"
				});
			this.work_details_div.appendChild(this.work_img);
			Event.observe(this.work_img, 'click', this.hideOverlay.bindAsEventListener(this));
			this.work_img.onclick = function () { return false; } // for Safari
			
			this.work_img_effect = new fx.Opacity(this.work_img);
			this.work_img_effect.hide();
			Event.observe(this.work_img, 'mouseover', function (e)
				{
					Event.stop(e);
					this.work_info_div.style.display = 'block';
				}.bindAsEventListener(this));
		}
		if (!this.overlay)
		{
			this.constructOverlay();
		}
		this.showOverlay();
		
		// put the title of the work we're showing in the work info div
		this.work_info_div.innerHTML = '<h3>'+link.work_title+'</h3>';
		
		// show the work div, in its final dimensions but with only the activity
		// indicator inside it, initially
		this.work_img_dims = link.work_dims;
		this.positionWorkImage(function ()
			{
				Element.setStyle(this.work_activity,
					{
						"display" : "block"
					});
				// load the clicked work
				new Ajax.Request(
					url,
					{
						method : 'get',
						onSuccess : this.writeWorkCallback,
						onFailure : this.failWorkCallback
					});
			}.bind(this));
	},
	
	failWork : function (request)
	{
		Element.setStyle(this.work_activity,
			{
				"display" : "none"
			});
		this.hideOverlay();
		alert('failure! ('+request.statusText+')');
	},
	
	writeWork : function (request)
	{
		var doc = request.responseXML;
		this.showWork(doc.documentElement);
	},
	
	constructOverlay : function ()
	{
		this.overlay = document.createElement('div');
		this.overlay.setAttribute('id', 'js_art_gallery_overlay');
		Element.setStyle(this.overlay,
			{
				"position" : "absolute",
				"left" : "0px",
				"top" : "0px",
				"width" : "100%",
				"height" : "100%",
				"display" : "none",
				"z-index" : "1010",
				"background-color" : "black"
			});
		this.overlay_effect = new fx.Opacity(this.overlay);
		this.overlay_effect.setOpacity(0.5);
		document.body.appendChild(this.overlay);
		Event.observe(this.overlay, 'click', this.hideOverlay.bindAsEventListener(this));
		this.overlay.onclick = function () { return false; } // for Safari
		Event.observe(window, 'resize', this.repositionWork.bindAsEventListener(this));
		Event.observe(this.overlay, 'mouseover', function (e)
			{
				Event.stop(e);
				this.work_info_div.style.display = 'none';
			}.bindAsEventListener(this));
	},
	
	getPageDimensions : function ()
	{
		var px,py;
		var test1 = document.body.scrollHeight;
		var test2 = document.body.offsetHeight
		if (test1 > test2) // all but Explorer Mac
		{
			px = document.body.scrollWidth;
			py = document.body.scrollHeight;
		}
		else // Explorer Mac;
		     //would also work in Explorer 6 Strict, Mozilla and Safari
		{
			px = document.body.offsetWidth;
			py = document.body.offsetHeight;
		}
		return { x : px, y : py };
	},
	
	getWindowDimensions : function ()
	{
		// gracias:
		// http://www.quirksmode.org/viewport/compatibility.html
		var x,y;
		if (self.innerHeight) // all except Explorer
		{
			x = self.innerWidth;
			y = self.innerHeight;
		}
		else if (document.documentElement && document.documentElement.clientHeight)
			// Explorer 6 Strict Mode
		{
			x = document.documentElement.clientWidth;
			y = document.documentElement.clientHeight;
		}
		else if (document.body) // other Explorers
		{
			x = document.body.clientWidth;
			y = document.body.clientHeight;
		}
		return { x : x, y : y };
	},
	
	getScreenDimensions : function ()
	{
		return { x : screen.availWidth, y : screen.availHeight };
	},
	
	getScrollOffset : function ()
	{
		// gracias:
		// http://www.quirksmode.org/viewport/compatibility.html
		var sx,sy;
		if (self.pageYOffset) // all except Explorer
		{
			sx = self.pageXOffset;
			sy = self.pageYOffset;
		}
		else if (document.documentElement && document.documentElement.scrollTop)
			// Explorer 6 Strict
		{
			sx = document.documentElement.scrollLeft;
			sy = document.documentElement.scrollTop;
		}
		else if (document.body) // all other Explorers
		{
			sx = document.body.scrollLeft;
			sy = document.body.scrollTop;
		}
		return { x : sx, y : sy };
	},
	
	repositionWork : function ()
	{
		if (Element.getStyle(this.overlay, "display") == "block")
		{
			this.showOverlay();
			this.positionWorkImage();
		}
	},
	
	showOverlay : function ()
	{
		var sd = this.getScreenDimensions();
		var so = this.getScrollOffset();
		this.old_scroll_offset = so;

		Element.setStyle(document.body,
			{
				"margin-left" : "-"+so.x+"px",
				"margin-top" : "-"+so.y+"px",
				"overflow" : "hidden"
			});
		
		Element.setStyle(this.overlay,
			{
				"width" : sd.x+"px",
				"height" : sd.y+"px",
				"display" : "block"
			});
	},
	
	hideOverlay : function (e)
	{
		if (e)
		{
			Event.stop(e);
		}
		this.hideWork();
		Element.setStyle(this.overlay, { "display" : "none" });
		Element.setStyle(document.body,
			{
				"margin-left" : "0px",
				"margin-top" : "0px",
				"overflow" : "auto"
			});
		window.scrollTo(this.old_scroll_offset.x, this.old_scroll_offset.y);
	},
	
	showWork : function (work)
	{
		// our web service tells us the width and height of the image before
		// we even load it, which makes things easier
		var imgelem = work.getElementsByTagName('img')[0];
		this.work_img_src = imgelem.getAttribute('src');
		this.work_img_description = work.getElementsByTagName('description')[0];
		if (this.work_img_description.firstChild)
		{
			this.work_img_description = this.work_img_description.firstChild.nodeValue;
		}
		else
		{
			this.work_img_description = '';
		}
		this.work_size = work.getAttribute('size');
		this.work_media = work.getAttribute('media');
		var work_img_preload = new Image();
		work_img_preload.onload = function ()
			{
				this.placeWorkImage();
			}.bind(this);
		work_img_preload.src = imgelem.getAttribute('src');
	},
	
	placeWorkImage : function ()
	{
		if (this.work_img_description.length != 0)
		{
			this.work_info_div.innerHTML = this.work_info_div.innerHTML+
				'<div class="description">'+this.work_img_description+'</div>';
		}
		if (this.work_size.length)
		{
			this.work_info_div.innerHTML = this.work_info_div.innerHTML+
				'<p class="size">'+this.work_size+'</p>';
		}
		if (this.work_media.length)
		{
			this.work_info_div.innerHTML = this.work_info_div.innerHTML+
				'<p class="media">'+this.work_media+'</p>';
		}
		Element.setStyle(this.work_activity, { "display" : "none" });
		this.work_img.setAttribute('src', this.work_img_src);
		Element.setStyle(this.work_img,
			{
				"display" : "block"
			});
		this.work_img_effect.toggle();
		
		this.positionWorkImage();
	},
	
	positionWorkImage : function (callback)
	{
		if (!this.work_img_dims)
		{
			return;
		}
		var wd = this.getWindowDimensions();
		var left, top, width, height;
		var adjimgwidth = this.work_img_dims.width+30;
		var adjimgheight = this.work_img_dims.height+30;
		if (adjimgwidth > wd.x || adjimgheight > wd.y)
		{
			// scale down
			var factor, factorx, factory;
			factorx = wd.x/adjimgwidth;
			factory = wd.y/adjimgheight;
			factor = Math.min(factorx, factory);
			adjimgheight = adjimgheight * factor;
			adjimgwidth = adjimgwidth * factor;
		}
		left = wd.x/2 - adjimgwidth/2;
		top = wd.y/2 - adjimgheight/2;
		width = adjimgwidth;
		height = adjimgheight;
			
		// see if the negative margins on body are affecting things
		if (this.old_scroll_offset.x != 0 || this.old_scroll_offset.y != 0)
		{
			var wpos = Position.cumulativeOffset(document.body.childNodes[0]);
			if (wpos[0] == 0 && wpos[1] == 0)
			{
				// in IE, the negative margin on body doesn't effect the
				// offsetTop/offsetLeft of anything inside, which is how this
				// detection works
				// we have to correct the positioning
				left = left + this.old_scroll_offset.x;
				top = top + this.old_scroll_offset.y;
			}
		}
		Element.setStyle(this.work_img,
			{
				"width" : (width-30)+"px",
				"height" : (height-30)+"px"
			});
		Element.setStyle(this.work_details_div,
			{
				"margin-left" : "0px",
				"margin-top" : "0px",
				"width" : (width-30)+"px",
				"height" : (height-30)+"px",
				"left" : (left+15)+"px",
				"top" : (top+15)+"px"
			});
		Element.setStyle(this.work_info_div,
			{
				"left" : (left+width-165)+"px",
				"top" : (top+15)+"px"
			});
		if (callback)
		{
			// don't initially show work info (will be shown onmouseover the image)
			//Element.setStyle(this.work_info_div, { "display" : "block" });
			Element.setStyle(this.work_details_div,
				{
					"display" : "block",
					"visibility" : "hidden"
				});
			var work_div_effect = new fx.Height(
				this.work_details_div,
				{
					duration: 1000,
					onComplete : callback
				});
			work_div_effect.hide();
			Element.setStyle(this.work_details_div,
				{
					"visibility" : "visible"
				});
			work_div_effect.custom(0, (height-30));
			
			/*
			var work_div_effect = new fx.Opacity(this.work_details_div,
				{
					onComplete : callback
				});
			work_div_effect.hide();
			Element.show(this.work_details_div);
			work_div_effect.custom(0, 1.0);
			*/
		}
	},
	
	hideWork : function ()
	{
		// hide the image
		this.work_img_effect.hide();
		Element.setStyle(this.work_img,
			{
				"display" : "none"
			});
		// hide the info
		Element.setStyle(this.work_info_div, { "display" : "none" });
		Element.setStyle(this.work_details_div, { "display" : "none" });
	},
	
	getCurrentCookie : function ()
	{
		var cookies = document.cookie;
		var pos = cookies.indexOf("js_art_gallery=");
		if (pos != -1)
		{
			var end = cookies.indexOf(";", pos);
			if (end == -1)
			{
				end = cookies.length;
			}
			var value = cookies.substring(pos+15, end);
			return value;
		}
		// default is none (false)
		return false;
	},
	
	setCurrentCookie : function (which) 
	{
		var nextyear = new Date(  );
		nextyear.setFullYear(nextyear.getFullYear()+1);
		document.cookie = "js_art_gallery="+which+"; expires="+nextyear.toGMTString();
	}
};