var gallery_ctrl = Class.create({
	initialize: function(gallery) {
		//controls a gallery
		this.gallery = gallery;
		this.items = [];
		this.tip_effects = {};
		this.transport = {};
		
		this.types = {
			TYPE_STD: 'gallery',
			TYPE_LIST: 'gallery-list'
		}
		
		if (this.gallery.hasClassName(this.types.TYPE_LIST)) {
			this.gallery_type = this.types.TYPE_LIST;
		} else {
			this.gallery_type = this.types.TYPE_STD;
		}
		
		if (gallery.readAttribute("class") != this.types.TYPE_LIST) {
			//parse items
			gallery.getElementsBySelector(".gallery-item").each(function(item) {
				this.activate(item);
			}, this);
		} else {
			gallery.select(".gallery-item").each(function(item) {
				var project_link = item.down("p.link a");
				
				if (project_link !== undefined) {
					item.observe("click", function(event) {
						target = event.findElement();
						
						if (target.tagName != "A") {
							location.href = project_link.readAttribute("href");
						}
					}.bind(this)).setStyle({
						'cursor': 'pointer'
					});
				}
			}, this);
		}
	},
	
	activate: function(item) {
		paras = item.getElementsBySelector("p");
		imgs = item.getElementsBySelector("img");
		
		if (paras.length > 1 && imgs.length == 1) {
			//item has more than one para and an image - initialize hover state
			var item_id = item.identify();
			
			this.items[item_id] = {
				'item': item
			};
			
			var tip = new Element("div", {
				'class': 'gallery-item-tip'
			}).setStyle({
				'padding': '0px'
			});
			
			//insert paras into tip container
			for (a = 1; a < paras.length; a++) {
				tip.insert(paras[a]);
			}
			
			//insert tip container into item
			item.insert({
				top: tip
			}).addClassName("has-tip");
			
			this.items[item_id].tip = tip;
			this.items[item_id].tip_target_height = imgs[0].offsetHeight;
			this.items[item_id].timer = null;
			
			item.observe("mouseenter", function(event) {
				this.hover(event, item_id, true);
			}.bind(this));
			
			item.observe("mouseleave", function(event) {
				this.hover(event, item_id, false);
			}.bind(this));
		}
		
		//scan links for clicking on item
		var links = item.getElementsBySelector("a[href != '']");
		
		if (links.length == 1) {
			//only one link present - create onclick event for item
			item.observe("click", function() {
				window.location.href = links[0].readAttribute("href");
			}).setStyle({
				'cursor': 'pointer'
			});
		}
	},
	
	hover: function(event, item_id, over) {
		var item, effect, tip, element, target_height;
		
		event.stop();
		
		item = this.items[item_id].item;
		tip = item.down(".gallery-item-tip");
		
		if (over) {
			item.addClassName("gallery-item-active");
			
			//animate in tip
			if (tip !== undefined) {
				tip.hide();
				
				if (this.tip_effects[item_id] !== undefined && this.tip_effects[item_id] !== null) {
					this.tip_effects[item_id].cancel();
				}
				
				this.tip_effects[item_id] = new Effect.Appear(tip, {
					duration: 0.3,
					afterFinish: function() {
						this.tip_effects[item_id] = null;
					}.bind(this)
				});
			}
		} else {			
			//animate out tip
			if (tip !== undefined) {
				if (this.tip_effects[item_id] !== undefined && this.tip_effects[item_id] !== null) {
					this.tip_effects[item_id].cancel();
				}
				
				this.tip_effects[item_id] = new Effect.Fade(tip, {
					duration: 0.3,
					afterFinish: function() {
						item.removeClassName("gallery-item-active");
						this.tip_effects[item_id] = null;
					}.bind(this)
				});
			} else {
				item.removeClassName("gallery-item-active");
			}
		}
	}
});

var small_gallery_ctrl = Class.create({
	initialize: function(gallery, settings) {
		var gallery_items;
		
		this.gallery = gallery;
		this.settings = settings || {};
		this.zoomer = null;
		this.animating = false;
		this.event = {};
		
		this.settings = ob_set_defaults(this.settings, {
			'width': null,
			'height': null,
			'append_class':null,
			'timeout': 0
		});
		
		//fetch items
		gallery_items = this.gallery.getElementsBySelector(".zoomview");
		if (gallery_items.length == 0) return false;
		
		gallery_items.each(function(el, index) {
			if (index == 0) {
				this.element_type = el.tagName;
			}
			
			el.observe("click", this.zoom.bind(this));
			el.setStyle({
				'cursor': 'pointer'
			});
		}, this);
		
		//create zoomer		
		this.zoomer = new Element("div", {
			'class': 'zoomview-loader' +
				(this.settings.append_class ? ' ' + this.settings.append_class : '')
		}).setStyle({
			'position': 'absolute',
			'visibility': 'hidden',
			'display': 'none',
			'overflow': 'hidden',
			'cursor': 'pointer',
			'backgroundColor': '#D50068'
		});
		
		$$("body")[0].insert(this.zoomer);
		
		this.zoomer.observe("click", this.unzoom.bind(this));
		document.observe("click", this.unzoom.bind(this));
	},
	
	zoom: function(event) {
		var zoomer_left, zoomer_right, zoomer_top, zoomer_bottom, anim_adjust_offset, el_pos,
			display_width, display_height, zoom_content, img_cacher;
		
		if (event !== undefined) {
			event.stop();
			this.event.el = event.findElement(this.element_type);
		}
		
		if (this.animating) return false;
		
		this.animating = true;
		
		el_pos = this.event.el.cumulativeOffset();
		
		//create new element based on current one
		src = this.event.el.down("span").readAttribute("style").match(/background-image:\s?url\(("|'?)([^)'"]*)(\1?)\)/i, '$1');
		if (src.length != 4) return false;
		
		if (this.zoomer.visible()) {
			//zoomer is currently visible - hide first
			new Effect.Morph(this.zoomer, {
				'style': new Hash({
					'width': '0px',
					'height': '0px',
					'left': (el_pos[0] + (this.event.el.offsetWidth / 2)) + 'px',
					'top': (el_pos[1] + (this.event.el.offsetHeight / 2)) + 'px'
				}),
				duration: 0.3,
				afterFinish: function(effect) {
					this.zoomer.setStyle({
						'display': 'none',
						'visibility': 'hidden'
					});
					
					this.animating = false;
					this.zoom();
				}.bind(this)
			});
		} else {
			//zoomer is hidden - clear contents
			this.zoomer.childElements().each(function(element) {
				element.remove();
			});
			
			//set background, display
			this.zoomer.setStyle({
				'display': 'block',
				'opacity': 1,
				'backgroundImage': 'url(' + src[2] + ')',
				'backgroundRepeat': 'no-repeat',
				'backgroundPosition': 'center center'
			});
			
			//create cacher image
			img_cacher = new Image();
			img_cacher.onload = function() {
				//add image
				var zoomer_img = new Element("img", {
					'src': src[2]
				}).setStyle({
					'visibility': 'hidden'
				});
				
				this.zoomer.insert(zoomer_img);
				
				//add any other content
				zoom_content = this.event.el.down(".zoom-content");
				
				if (zoom_content != null) {
					this.zoomer.insert(zoom_content.cloneNode(true));
				}
				
				//get document boundaries
				bounds = $(document.body).getDimensions();
				
				//set zoomer dimensions and coords (based on image and callee)
				this.zoomer.setStyle({
					'visibility': 'visible',
					'width': this.event.el.offsetWidth + 'px',
					'height': this.event.el.offsetHeight + 'px',
					'left': el_pos[0] + 'px',
					'top': el_pos[1] + 'px'
				});
				
				display_width = (this.settings.width || zoomer_img.offsetWidth);
				display_height = (this.settings.height || zoomer_img.offsetHeight);
				
				zoomer_left = (el_pos[0] - (display_width / 2) + (this.event.el.offsetWidth / 2));
				zoomer_top = (el_pos[1] - (display_height / 2) + (this.event.el.offsetHeight / 2));
				zoomer_right = zoomer_left + display_width;
				zoomer_bottom = zoomer_top + display_height;
				
				//check boundaries aren't overlapped - allowing for animation adjustments
				anim_adjust_offset = 25;
				
				if ((zoomer_right + anim_adjust_offset) > bounds.width) {
					zoomer_left = (zoomer_left - (zoomer_right - bounds.width) - anim_adjust_offset);
				}
				
				if ((zoomer_bottom + anim_adjust_offset) > bounds.height) {
					zoomer_top = (zoomer_top - (zoomer_bottom - bounds.height) - anim_adjust_offset);
				}
				
				//animate into position
				new Effect.Morph(this.zoomer, {
					'style': new Hash({
						'width': display_width + 'px',
						'height': display_height + 'px',
						'left': zoomer_left + 'px',
						'top': zoomer_top + 'px'
					}),
					duration: 0.5,
					transition: Effect.Transitions.spring,
					afterFinish: function() {
						this.animating = false;
						this.event = {};
						
						if (this.settings.timeout > 0) {
							window.setTimeout(this.unzoom.bind(this), (this.settings.timeout * 1000));
						}
					}.bind(this)
				});
			}.bind(this);
			
			//assign source
			img_cacher.src = src[2];
		}
	},
	
	unzoom: function() {
		if (this.animating || !this.zoomer.visible()) return false;
		
		this.animating = true;
		
		new Effect.DropOut(this.zoomer, {
			duration: 0.5,
			afterFinish: function() {
				this.zoomer.setStyle({
					'display': 'none',
					'visibility': 'hidden'
				});
				
				this.animating = false;
			}.bind(this)
		});
		
		this.zoomer.childElements().each(function(child) {
			child.remove();
		});
	}
});
