/*
	TODO:
		1. thumbnails transition animation
		2. thumb rollovers should access options vars (currently hard-coded)
		3. when resizing image widths, make sure the tallest size for the main_image_container is calculated from the resized height
		4. loader
*/
var CE_Gallery_Display_Controller = new Class({
    options: {
		id: null,
		gallery_id: null,
		key: null,
		datasource: null,
		containers: [ "main_image_container", "thumbnails_container", "thumbs_paging_top", "thumbs_paging_bottom" ], // containers that are initially hidden and should be shown once the gallery is initialized
		outer_image_container: "main_image_container", // outer container; we resize it to the size of the tallest image + outer_image_container_offset so the bottom of the page doesn't jump
		main_image_container: "main_image", // where we inject the large image
		thumbnails_container: "thumbnails", // where we attach all the thumbs and associated elements
		caption_container: "caption", // where we set the caption of the currently selected image
		current_status_containers: [ "loc_top", "loc_bottom" ],
		prev_next_containers: [ "prev_next_top", "prev_next_bottom" ],
		thumbs_paging_containers: [ "thumbs_paging_top", "thumbs_paging_bottom" ], // containers for attaching the thumbnails paging components to
		application_webroot: null,
		outer_image_container_offset: 100, // accounts paging, hr and caption  elements when sizing the image container
		thumbnails_per_row: 3,
		thumbnails_per_page: 15,
		fx_duration: 200,
		thumbnail_opacity: 0.5,
		resize_thumb_width: 0,
		resize_image_width: 0, // set to zero to use the image's natural width/height
		slideshow: true,
		slideshow_interval: 5000,
		play_link_html: "Play Slideshow&nbsp;&raquo;",
		pause_link_html: "Pause Slideshow&nbsp;&raquo;",
		selected_img: null, // passed as a query param (e.g. "&img=[unid]"); the image to default to; defaults to the first image if it's null
		send_to_friend: false
    },

    initialize: function(options) {
		this.setOptions(options);
		this.ajax = null;
		this.interval = null;
		
		this.outer_image_container = $(this.options.outer_image_container);
		this.main_image_container = $(this.options.main_image_container);
		this.thumbnails_container = $(this.options.thumbnails_container);
		this.caption = $(this.options.caption_container);
		
		this.containers = [];
		for (var x = 0; x < this.options.containers.length; x++) {
			this.containers.push($(this.options.containers[x]));
		}
		
		this.slideshow_container = null;
		this.play_link = null
		this.pause_link = null;
		if (this.options.slideshow) {
			this.slideshow_container = $("slideshow_controls");
			
			this.play_link = document.createElement("a");
			this.play_link.setAttribute("href", "javascript:" + this.options.id + ".play()");
			this.play_link.setAttribute("id", "slideshow_play_link");
			//this.play_link.appendChild(document.createTextNode("Play"));
			this.play_link.innerHTML = this.options.play_link_html;
			this.slideshow_container.appendChild(this.play_link);
			
			this.pause_link = document.createElement("a");
			this.pause_link.setAttribute("href", "javascript:" + this.options.id + ".pause()");
			this.pause_link.setAttribute("id", "slideshow_pause_link");
			//this.play_link.appendChild(document.createTextNode("Play"));
			this.pause_link.innerHTML = this.options.pause_link_html;
			this.pause_link.style.cssText = "display:none";
			this.slideshow_container.appendChild(this.pause_link);
			
			this.containers.push(this.slideshow_container);	
		}
		
		this.current_status_containers = [];
		for (var x = 0; x < this.options.current_status_containers.length; x++) {
			this.current_status_containers.push($(this.options.current_status_containers[x]));
		}
		
		this.prev_next_containers = [];
		for (var x = 0; x < this.options.prev_next_containers.length; x++) {
			this.prev_next_containers.push($(this.options.prev_next_containers[x]));
		}
		
		this.images = [];
		//this.main_image = null;
		this.current_image = 0;
		this.tallest_image_height = 0;
		//this.tallest_page_height = 0;
		
		this.num_pages = 0;
		this.current_page = 1;
	},
	
	/** gets our images and image metadata */
	init: function() {
		var do_ajax = false;
		if ($defined(this.options.gallery_id)) {
			pars = "method=get_images&target=" + this.options.id + "&id=" + this.options.gallery_id;
			do_ajax = true;
		} else if ($defined(this.options.key)) {
			pars = "method=retrieve_photos&target=" + this.options.id + "&key=" + encodeURIComponent(this.options.key);
			do_ajax = true;
		}
		
		if (do_ajax) {
			//prompt("pars:", pars);
	
			/*this.ajax = new Ajax(this.options.datasource, {
				data: pars,
				onComplete: this.inited
			}).request();*/
			
			this.ajax = new Request({
				url: this.options.datasource,
				data: pars,
				onSuccess: this.inited
			}).send();
		}
	},
	
	/** callback handler for the ajax call in init; basically just calls populate to finish initializing the gallery */
	inited: function(request) {
		r = JSON.decode(request);
		target = eval(r.target);
		
		target.populate(r);
	},
	
	populate_images: function(r) {
		for (var x = 0; x < r.images.length; x++) {
			var image_container = document.createElement("div");
			image_container.setAttribute("id", "image_container_" + x);
			if (x !== 0) {
				image_container.setAttribute("style", "display:none");
				image_container.style.cssText = "display:none";
			}
			
			var image = document.createElement("img");
			image.setAttribute("src", this.options.application_webroot + r.images[x].path);
			
			if (this.options.resize_image_width === 0) {
				image.setAttribute("width", r.images[x].width);
				image.setAttribute("height", r.images[x].height);
			} else {
				image.setAttribute("width", this.options.resize_image_width);
				// IE is dumb and doesn't autosize the height if given just the width, so calculate and set it
				image.setAttribute("height", this.options.resize_image_width * r.images[x].height / r.images[x].width);
				//image.setAttribute("height", Math.ceil(this.options.resize_image_width * r.images[x].height / r.images[x].width));
			}
			
			image.setAttribute("alt", r.images[x].caption);
			
			if (r.images[x].height > this.tallest_image_height) { this.tallest_image_height = r.images[x].height; }
			
			
			var c = r.images[x].caption;
			
			if (this.options.send_to_friend === true) {
				c += " <a href=\"javascript:" + this.options.id + ".send_to_friend('" + r.images[x].id + "','" + r.images[x].caption + "')\">Send to Friend&nbsp;&raquo;</a>";	
			}
			
			this.images.push({
				"id": r.images[x].id,
				"caption": c
			});
			
			image_container.appendChild(image);
			this.main_image_container.appendChild(image_container);
		}
	},
	
	render_paging: function(parent) {
		var x, a;
		var paging = document.createElement("div");
		var paging_loc = document.createElement("div");
		paging_loc.setAttribute("id", parent + "_loc");
		var paging_links = document.createElement("div");
		
		paging.setAttribute("class", "paging");
		paging.setAttribute("className", "paging");
		paging_loc.setAttribute("class", "loc");
		paging_loc.setAttribute("className", "loc");
		paging_links.setAttribute("class", "links");
		paging_links.setAttribute("className", "links");
		
		paging_loc.appendChild(document.createTextNode("Page 1 of " + this.num_pages));

		a = document.createElement("a");
		a.setAttribute("href", "javascript:" + this.options.id + ".prev_page()");
		//a.appendChild(document.createTextNode("prev"));
		a.innerHTML = "&laquo;&nbsp;Previous";
		paging_links.appendChild(a);
		
		for (x = 0; x < this.num_pages; x++) {
			a = document.createElement("a");
			a.setAttribute("id", parent + "_link_" + (x + 1));
			a.setAttribute("href", "javascript:" + this.options.id + ".page(" + (x + 1) + ")");
			if (x === 0) {
				a.setAttribute("class", "selected");
				a.setAttribute("className", "selected");
			}
			a.appendChild(document.createTextNode(x + 1));
			paging_links.appendChild(a);
		}
		
		a = document.createElement("a");
		a.setAttribute("href", "javascript:" + this.options.id + ".next_page()");
		//a.appendChild(document.createTextNode("next"));
		a.innerHTML = "Next&nbsp;&raquo;";
		paging_links.appendChild(a);
		
		paging.appendChild(paging_loc);
		paging.appendChild(paging_links);
		this.clear_div(paging);

		$(parent).appendChild(paging);
	},
	
	populate_thumbs: function(r) {
		var x, thumbnail, a, page_count = 1;
		
		this.num_pages = Math.ceil(r.images.length / this.options.thumbnails_per_page);
		
		if (this.num_pages > 1) {
			for (x = 0; x < this.options.thumbs_paging_containers.length; x++) {
				this.render_paging(this.options.thumbs_paging_containers[x]);
			}
		}

		var page_container = document.createElement("div");
		page_container.setAttribute("id", "page_container_" + page_count);
		page_container.setAttribute("style", "margin:0px;padding:0px");
		page_container.style.cssText = "margin:0px;padding:0px";
		
		var row_container = document.createElement("div");

		//page_container.appendChild(row_container);
		
		for (x = 0; x < r.images.length; x++) {
			thumbnail = $(document.createElement("img"));
			thumbnail.setAttribute("id", "thumbnail_" + x);
			thumbnail.setAttribute("src", this.options.application_webroot + r.images[x].thumb_path);
			
			if (this.options.resize_thumb_width === 0) {
				thumbnail.setAttribute("width", r.images[x].thumb_width);
				thumbnail.setAttribute("height", r.images[x].thumb_height);
			} else {
				thumbnail.setAttribute("width", this.options.resize_thumb_width);
				// IE is dumb and doesn't autosize the height if given just the width, so calculate and set it
				thumbnail.setAttribute("height", this.options.resize_thumb_width * r.images[x].thumb_height / r.images[x].thumb_width);
				//thumbnail.setAttribute("height", Math.ceil(this.options.resize_thumb_width * r.images[x].thumb_height / r.images[x].thumb_width));
			}
			
			thumbnail.setAttribute("alt", r.images[x].caption);
			if (x === 0) { 
				thumbnail.setAttribute("class", "selected");
				thumbnail.setAttribute("className", "selected");
			}
			
			if (x !== 0 ) { thumbnail.setStyle("opacity", this.options.thumbnail_opacity); }
			
			thumbnail.addEvent(
				"mouseover", 
				function (e) { 
					e = new Event(e);
					//e.target.setStyle("opacity", 1);
					var up = new Fx.Tween(e.target, { duration:200 }).start("opacity", e.target.getStyle("opacity"), 1);
				}
			);
			
			thumbnail.addEvent(
				"mouseout",
				function (e) {
					e = new Event(e);
					if (e.target.className.indexOf("selected") === -1) { 
						//e.target.setStyle("opacity",0.5);
						var down = new Fx.Tween(e.target, { duration:200 }).start("opacity", e.target.getStyle("opacity"), 0.5);
					} 
				}
			);
			
			// create our thumbnail and its link
			a = document.createElement("a");
			a.setAttribute("href", "javascript:" + this.options.id + ".do_image(" + x + ")");
			a.appendChild(thumbnail);

			//this.thumbnails_container.appendChild(anchor);
			row_container.appendChild(a);
			
			if ((x + 1) % this.options.thumbnails_per_row === 0) {
				thumbnail.className = "no_margin";
				this.clear_div(row_container);
				page_container.appendChild(row_container);
				row_container = document.createElement("div");
			} else if (x == (r.images.length - 1)) {
				// we're not at the end of a row; just create our clear div and attach whatever pics were in the last row
				this.clear_div(row_container);
				page_container.appendChild(row_container);			 
			}
			
			if ((x + 1) % this.options.thumbnails_per_page === 0) {
				this.clear_div(page_container);
				this.thumbnails_container.appendChild(page_container);
				/*var h = $("page_container_" + page_count).getCoordinates().height; alert("h: " + h);
				if (h > this.tallest_page_height) { this.tallest_page_height = h; }*/
				page_container = document.createElement("div");
				page_container.setAttribute("id", "page_container_" + (++page_count));
				page_container.setAttribute("style", "display:none;margin:0px;padding:0px");
				page_container.style.cssText = "display:none;margin:0px;padding:0px";
			} else if (x == (r.images.length - 1)) {
				this.clear_div(page_container);
				this.thumbnails_container.appendChild(page_container);
				/*var h = $("page_container_" + page_count).getCoordinates().height; alert("h: " + h);
				if (h > this.tallest_page_height) { this.tallest_page_height = h; }*/
			}
			
		}
	},
	
	clear_div: function(elem) {
		var clear_div = document.createElement("div");
		clear_div.setAttribute("style", "clear:both;margin:0px;padding:0px");
		clear_div.style.cssText = "clear:both;margin:0px;padding:0px";
		elem.appendChild(clear_div);
	},
	
	populate: function(r) {
		this.populate_images(r);
		this.populate_thumbs(r);
		
		// set the height of the outer image container to prevent the bottom of the page from 'jumping' when image height changes
		//this.outer_image_container.setStyles({ height:(this.tallest_image_height + this.options.outer_image_container_offset) });
				
		// set up our previous/next containers
		for (var x = 0; x < this.prev_next_containers.length; x++) {
			this.prev_next_containers[x].innerHTML = "<a href=\"javascript:" + this.options.id + ".previous()\">&laquo;&nbsp;Previous</a> | <a href=\"javascript:" + this.options.id + ".next()\">Next&nbsp;&raquo;</a>";	
		}

		// print any current status messages (e.g. "Image [x] of [total]")
		this.do_current_status();
		
		// set our caption
		this.caption.innerHTML = this.images[this.current_image].caption;
		
		if ($defined(this.options.selected_img)) {
			var i = this.get_image_by_unid(this.options.selected_img);
			if ($defined(i)) {
				this.do_image(i);
				this.check_page();
			}
		}
		
		// all populated; show hidden elements
		this.reveal();
	},
	
	reveal: function() {
		for (var x = 0; x < this.containers.length; x++) {
			//this.containers[x].style.display = "";
			var elem_to_appear = $(this.containers[x]);
			elem_to_appear.setStyles({ opacity: 0, display:"block" });
			var a = new Fx.Tween(elem_to_appear, { duration:this.options.fx_duration }).start("opacity", 0, 1);
		}
	},
	
	/** prints the "Image [x] of [total]" message to all current status containers for the gallery */
	do_current_status: function() {
		for (var x = 0; x < this.current_status_containers.length; x++) {
			this.current_status_containers[x].innerHTML = "Image " + (this.current_image + 1) + " of " + this.images.length;	
		}
	},
	
	do_image: function(which) {
		if (this.current_image !== which) {
			var d = $("thumbnail_" + this.current_image);
			
			if (d.className.indexOf("no_margin") != -1) {
				d.className = "no_margin";
			} else {
				d.className = "";
			}
			
			var u = $("thumbnail_" + which);
			u.className += " selected";

			var down = new Fx.Tween(d, { duration:this.options.fx_duration }).start("opacity", 1, this.options.thumbnail_opacity);
			var up = new Fx.Tween(u, { duration:this.options.fx_duration }).start("opacity", u.getStyle("opacity"), 1);
	
			this.transition("image_container_" + this.current_image, "image_container_" + which);
			
			this.current_image = which;
			
			// set our caption
			this.caption.innerHTML = this.images[which].caption;
			
			// print any current status messages (e.g. "Image [x] of [total]")
			this.do_current_status();
		}
	},
	
	transition: function(from, to) {
		var f = new Fx.Tween(from, { duration:this.options.fx_duration, onComplete:function(elem) { elem.style.display = "none"; } });
		var t = new Fx.Tween(to, { duration:this.options.fx_duration });
		
		f.start("opacity", 1, 0).chain(
			function() {
				$(to).setStyles({ opacity: 0, display:"block" });
				t.start("opacity", 0, 1);
			}
		);
	},
	
	page: function(which) {
		if (this.current_page !== which) {
			/*
			$("page_container_" + this.current_page).style.display = "none";
			$("page_container_" + which).style.display = "";
			*/
			this.transition("page_container_" + this.current_page, "page_container_" + which);
			
			for (x = 0; x < this.options.thumbs_paging_containers.length; x++) {
				$(this.options.thumbs_paging_containers[x] + "_link_" + this.current_page).className = "";
				$(this.options.thumbs_paging_containers[x] + "_link_" + which).className = "selected";
				$(this.options.thumbs_paging_containers[x] + "_loc").innerHTML = "Page " + which + " of " + this.num_pages;
			}
			
			this.current_page = which;
		}
	},
	
	next_page: function() {
		if (this.current_page === this.num_pages) {
			this.page(1);
		} else {
			this.page(this.current_page + 1);
		}
	},
	
	prev_page: function() {
		if (this.current_page === 1) {
			this.page(this.num_pages);
		} else {
			this.page(this.current_page - 1);
		}
	},
	
	check_page: function() {
		var p = Math.ceil((this.current_image + 1) / this.options.thumbnails_per_page);
		if (p !== this.current_page) { this.page(p); }
	},
	
	next: function() {
		if (this.current_image == (this.images.length - 1)) {
			this.do_image(0);
		} else {
			this.do_image(this.current_image + 1);
		}
		this.check_page();
	},
	
	previous: function() {
		if (this.current_image == 0) {
			this.do_image(this.images.length - 1);
		} else {
			this.do_image(this.current_image - 1);
		}
		this.check_page();
	},
	
	play: function() {
		this.next();
		this.interval = setInterval(this.options.id + ".next()", this.options.slideshow_interval);
		this.transition(this.play_link, this.pause_link);
	},
	
	pause: function() {
		clearInterval(this.interval);
		this.transition(this.pause_link, this.play_link);
	},
	
	get_image_by_unid: function(unid) {
		for(var x = 0; x < this.images.length; x++) {
			if (this.images[x].id === unid) {
				return x;
			}
		}
		return null;
	},
	
	send_to_friend: function(unid,caption) {
		//var url = this.options.application_webroot + window.location.pathname.substr(1, window.location.pathname.length) + "?id=" + this.options.gallery_id + "&img=" + unid;
		var url = this.options.application_webroot + "send_url.cfm?ref=" + window.location + "%26img=" + unid;
		if(caption !="") {
			url +=   "&pt=" + caption;	
		}
		window.location.href = url;
	}
	
});

CE_Gallery_Display_Controller.implement(new Options);
