/*
 * (c) Kari Lavikka
 */

function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}

var PictureBrowser = Class.create({
	initialize: function(imagesId) {
		this.pictureFrame = false;
		this.imgElement = false;
		this.captionElement = false;
		this.numberElement = false;
		this.closeButton = false;

		this.naviLeft = false;
		this.naviRight = false;

		this.shader = false;

		this.imagesDiv = false;
		this.thumbLinks = false;
		this.currentThumbLink = false;
		this.pendingImage = false;
		this.hashMonitorEnabled = true;

		this.keyNavigation = true;
		this.fadeDuration = 0.1;

		this.ie = /msie/i.test(navigator.userAgent) && !window.opera;
		this.pictureFirst = false; // url was to an image
		this.inTrasition = false; // effect in effect

		this.pictureFrame = new Element("div");
		this.pictureFrame.id = "pictureFrame";
		this.pictureFrame.setOpacity(0);
		this.pictureFrame.style.visibility = "hidden";

		this.imgElement = new Element("img");
		this.imgElement.style.cursor = "pointer";
		this.pictureFrame.appendChild(this.imgElement);

		//document.cookie = 'ppkcookie1=testcookie; expires=Thu, 2 Aug 2001 20:47:11 UTC; path=/';
		var keyNavigationCookie = readCookie('keyNavigation');
		if (keyNavigationCookie) {
			if (keyNavigationCookie == "disabled") {
				this.keyNavigation = false;
			}
			if (keyNavigationCookie == "enabled") {
				this.keyNavigation = true;
			}
		}
		//alert(this.keyNavigation);

		Event.observe(this.imgElement, 'load', function() {
			var scrollTop = document.viewport.getScrollOffsets()[1] + 5;
			var thumbsTop = Element.cumulativeOffset(this.imagesDiv)[1];

			var top = (scrollTop > thumbsTop ? scrollTop : thumbsTop);
			this.pictureFrame.style.left = (document.viewport.getWidth() - this.pictureFrame.offsetWidth) / 2 + "px";
			this.pictureFrame.style.top = top + "px"; 

			this.naviLeft.style.top = (top + 40) + "px"
			this.naviRight.style.top = (top + 40) + "px"

			if (this.pictureFrame.style.visibility != "visible") this.showPictureFrame();

		}.bind(this));

		Event.observe(window, 'resize', function() {
			this.pictureFrame.style.left = (document.viewport.getWidth() - this.pictureFrame.offsetWidth) / 2 + "px";
		}.bind(this));

		Event.observe(this.imgElement, 'click', function(event) {
			Event.stop(event);
			if (this.inTransition) return;
			this.pendingImage = false;
			this.hidePictureFrame();
			this.goBack();
		}.bind(this));

		this.keyToggle = new Element("a", {id: "keyToggle", href: "#"});
		this.keyToggle.className = ( this.keyNavigation ? "" : "disabled" );
		this.keyToggle.update("Navigate with arrow keys");
		this.pictureFrame.appendChild(this.keyToggle);

		Event.observe(this.keyToggle, "click", function(event) {
			Event.stop(event);
			this.toggleKeyNavigation();
		}.bindAsEventListener(this));

		this.numberElement = new Element("p", {id: "number"});
		this.pictureFrame.appendChild(this.numberElement);
	
		this.captionElement = new Element("p", {id: "caption"});
		this.captionElement.style.display = "none"
		this.pictureFrame.appendChild(this.captionElement);

		this.closeButton = new Element("a", {id: "close", href: "#"});
		this.closeButton.update("Close");
		this.pictureFrame.appendChild(this.closeButton);

		Event.observe(this.closeButton, "click", function(event) {
			Event.stop(event);
			if (this.inTransition) return;
			this.pendingImage = false;
			this.hidePictureFrame();
			this.goBack();
		}.bindAsEventListener(this));

		Event.observe(document, "keydown", function(event) {
			if (!this.currentThumbLink || this.inTransition) {
				// Event.stop(event);
				return;
			}

			switch (event.keyCode) {
			case 167: // section
			case 192: // grave accent
				this.toggleKeyNavigation();
				break;
			case 27: // esc
				if ( this.keyNavigation ) {
					if (this.inTransition) return;
					this.pendingImage = false;
					this.hidePictureFrame();
					this.goBack();
				}
				break;
			case 37: // prev
				if ( this.keyNavigation ) this.navigate(-1);
				break;
			case 39: // next
				if ( this.keyNavigation ) this.navigate(1);
				break;
			default:
				return;
			}
		}.bindAsEventListener(this));

		//this.imagesDiv = $("thumbs");
		if (imagesId) {
			this.imagesDiv = $(imagesId);
		}
		else {
			this.imagesDiv = $("thumbs");
		}

		document.body.appendChild(this.pictureFrame);


		this.naviLeft = new Element("div", {id: "naviLeft", "class": "naviButton"});
		this.naviLeft.addClassName("naviButton"); // IE8 kludge
		this.naviLeft.setStyle({opacity: 0, visibility: "hidden"});
		e = new Element("div", {"class": "naviImage"});
		e.addClassName("naviImage"); // IE8 kludge
		this.naviLeft.appendChild(e);
		e = new Element("div", {"class": "naviText"});
		e.addClassName("naviText"); // IE8 kludge
		e.update("Previous");
		this.naviLeft.appendChild(e);
		Event.observe(this.naviLeft, "click", function(e) { Event.stop(e); this.navigate(-1); return false }.bindAsEventListener(this));
		document.body.appendChild(this.naviLeft);

		this.naviRight = new Element("div", {id: "naviRight", "class": "naviButton"});
		this.naviRight.addClassName("naviButton"); // IE8 kludge
		this.naviRight.setStyle({opacity: 0, visibility: "hidden"});
		e = new Element("div", {"class": "naviImage"});
		e.addClassName("naviImage"); // IE8 kludge
		this.naviRight.appendChild(e);
		e = new Element("div", {"class": "naviText"});
		e.addClassName("naviText"); // IE8 kludge
		e.update("Next");
		this.naviRight.appendChild(e);
		Event.observe(this.naviRight, "click", function(e) { Event.stop(e); this.navigate(1); return false }.bindAsEventListener(this));
		document.body.appendChild(this.naviRight);

		this.shader = new Element("div", {id: "shader"});
		this.shader.setOpacity(0);
		this.shader.style.visibility = "hidden";

		this.imagesDiv.appendChild(this.shader);

		//this.thumbLinks = $A(this.imagesDiv.getElementsByTagName("a"));

		this.thumbLinks = new Array();
		links = this.imagesDiv.getElementsByTagName("a");
		for (var n = 0; n < links.length; n++) {
			if(links[n].href && /[.](jpg|gif|png)$/.exec(links[n].href)) {
				this.thumbLinks.push(links[n]);
			}
		}

		this.thumbLinks.each(function(item) {
			Event.observe(item, 'click', this.updatePicture.bindAsEventListener(this, item)); // TODO: this
		}.bind(this));

		this.updatePictureFromHash();

		setTimeout(this.hashMonitor.bind(this), 500);
	},

	updatePicture: function(event, a) {
		if (event) Event.stop(event);
		if (this.inTransition) return;

		this.hashMonitorEnabled = false;
		window.location.hash = /[^\/]+$/.exec(a.href)[0];
		//alert(/[^\/]+$/.exec(a.href)[0]);
		this.imgElement.src = a.href;
		
		var imgElement = a.firstChild;
		if (imgElement.title) {
			this.captionElement.innerHTML = imgElement.title;
			this.captionElement.style.display = "block";
		} else {
			this.captionElement.style.display = "none";
		}

		var x = this.thumbLinks.indexOf(a) + 1;
		//this.numberElement.textContent = "Image " + x + " / " + this.thumbLinks.size();
		this.numberElement.update("Image " + x + " / " + this.thumbLinks.size());
		//if(this.numberElement.textContent) { alert(this.numberElement.textContent); }

		this.currentThumbLink = a;
	},

	goBack: function() {
		if (document.location.hash.length > 1) {
			if (!this.ie && !this.pictureFirst && window.location.hash.length > 1) {
				history.back();
			} else {
				window.location.hash = "#";
				this.pictureFirst = false;
			}
		}

	},

	updatePictureFromHash: function() {
		if (window.location.hash.length > 1) {
			var links = this.imagesDiv.getElementsByTagName("a");
			var r = new RegExp(/[^#]+$/.exec(window.location.hash)[0] + "$");
			for (var n = 0; n < links.length; n++) {
				if (r.test(links[n].href)) {
					this.updatePicture.bind(this, null, links[n])();
					this.pictureFirst = true;
					break;
				}
			}
		}
	},

	hidePictureFrame: function() {
		var effects = new Array();

		effects.push(new Effect.Opacity(this.pictureFrame, {
			sync: true, from: 1, to: 0,
			afterFinish: function() { this.pictureFrame.style.visibility = "hidden"; }.bind(this)
		}));

		if (!this.pendingImage) {
			effects.push(new Effect.Opacity(this.shader, {
				sync: true, from: 0.7, to: 0,
				afterFinish: function() { this.shader.style.visibility = "hidden"; }.bind(this)
			}));

		}

		var x = this.pendingImage ? this.thumbLinks.indexOf(this.pendingImage) : -1;

		if (x < 1) {
			effects.push(new Effect.Opacity(this.naviLeft, {
				sync: true, from: 1, to: 0,
				afterFinish: function() { this.naviLeft.style.visibility = "hidden"; }.bind(this)
			}));
		}

		if (x < 0 || x > this.thumbLinks.size() - 2) {
			effects.push(new Effect.Opacity(this.naviRight, {
				sync: true, from: 1, to: 0,
				afterFinish: function() { this.naviRight.style.visibility = "hidden"; }.bind(this)
			}));
		}

		new Effect.Parallel(effects, {
			duration: this.fadeDuration,
			afterFinish: function() {
				this.inTransition = false;

				// prevent scrollbars if picture size changes before repositioning
				this.pictureFrame.style.top = "0";
				this.pictureFrame.style.left = "0";

				if (this.pendingImage) {
					this.updatePicture(false, this.pendingImage);
					this.pendingImage = false;
				} else {
					this.hashMonitorEnabled = true;
				}
			}.bind(this),
			beforeStart: function() { this.inTransition = true; }.bind(this)
		});
		/*
		this.shader.setOpacity(0);
		this.shader.style.visibility = "hidden";
		this.pictureFrame.style.visibility = "hidden";
		*/
	},

	showPictureFrame: function() {
		var effects = new Array();

		effects.push(new Effect.Opacity(this.pictureFrame, {
			sync: true, from: 0, to: 1,
			beforeStart: function() { this.pictureFrame.style.visibility = "visible"; }.bind(this)
		}));

		if (this.shader.style.visibility == "hidden") {
			effects.push(new Effect.Opacity(this.shader, {
				sync: true, from: 0, to: 0.7,
				beforeStart: function() { this.shader.style.visibility = "visible"; }.bind(this)
			}));
		}

		var x = this.thumbLinks.indexOf(this.currentThumbLink);

		if (x > 0 && this.naviLeft.style.visibility == "hidden") {
			effects.push(new Effect.Opacity(this.naviLeft, {
				sync: true, from: 0, to: 1,
				beforeStart: function() { this.naviLeft.style.visibility = "visible"; }.bind(this)
			}));
		}

		if (x < this.thumbLinks.size() - 1 && this.naviRight.style.visibility == "hidden") {
			effects.push(new Effect.Opacity(this.naviRight, {
				sync: true, from: 0, to: 1,
				beforeStart: function() { this.naviRight.style.visibility = "visible"; }.bind(this)
			}));
		}
		
		new Effect.Parallel(effects, {
			duration: this.fadeDuration,
			afterFinish: function() {
				this.inTransition = false;

				// preload next/prev
				var x = this.thumbLinks.indexOf(this.currentThumbLink);
				if (x > 0) {
					var i = new Image();
					i.src = this.thumbLinks[x - 1].href;
				}
				if (x < this.thumbLinks.size() - 1) {
					var i = new Image();
					i.src = this.thumbLinks[x + 1].href;
				}
				this.hashMonitorEnabled = true;
			}.bind(this),
			beforeStart: function() { this.inTransition = true; }.bind(this)
		});
		/*
		this.pictureFrame.style.visibility = "visible";
		this.shader.style.visibility = "visible";
		this.shader.setOpacity(0.7);
		//this.updatePicturePictureFromHash();
		*/
	},

	// kludge for monitoring back/forward. IE8 has an onHashChange event but no other browsers has it atm.
	hashMonitor: function() {
		if (!this.inTransition && this.hashMonitorEnabled) {
			if (this.pictureFrame.style.visibility == "visible" && (!window.location.hash || window.location.hash == "#")) {
				this.hidePictureFrame();
			} else if (this.pictureFrame.style.visibility == "hidden" && window.location.hash.length > 1) {
				this.updatePictureFromHash();
			}
		}
		setTimeout(this.hashMonitor.bind(this), 200);
	},

	navigate: function(direction) {
		var x = this.thumbLinks.indexOf(this.currentThumbLink);

		switch (direction) {
		case -1: // prev
			if (x > 0) {
				x--;
			} else {
				return;
			}
			break;
		case 1: // next
			if (x < this.thumbLinks.size() - 1) {
				x++;
			} else {
				return;
			}
			break;
		default:
			return;
		}

		this.pictureFirst = true; // can't go back to thumbnail view using history.back();
		this.hashMonitorEnabled = false;
		this.pendingImage = this.thumbLinks[x];
		this.hidePictureFrame();
	},

	toggleKeyNavigation: function() {
		this.keyNavigation = ( this.keyNavigation ? false : true );
		this.keyToggle.className = ( this.keyNavigation ? "" : "disabled" );
		createCookie('keyNavigation', ( this.keyNavigation ? "enabled" : "disabled" ), 7);
	}

});

function pblaunch() {
    //illpb = new PictureBrowser("illustrationthumbs");
    //pripb = new PictureBrowser("printthumbs");
    //photopb = new PictureBrowser("photothumbs");
    pb = new PictureBrowser("thumbs");
}
//Event.observe(document, 'dom:loaded', PictureBrowser.init.bindAsEventListener(PictureBrowser));
//Event.observe(document, 'dom:loaded', function() {PictureBrowser.init()}.bindAsEventListener());
Event.observe(document, 'dom:loaded', pblaunch.bindAsEventListener());



