/***************************************************************
*  Copyright notice
*
*  (c) 2006 - 2007 Alex Buchgeher
*  All rights reserved
*
*  This script is part of the TYPO3 project. The TYPO3 project is
*  free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  The GNU General Public License can be found at
*  http://www.gnu.org/copyleft/gpl.html.
*
*  This script is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/


var DEBUG = true;
function debug(mixed) {
	if(!DEBUG) { return; }
	var debugWrapper = $("debug");
	if(debugWrapper == undefined) {
		debugWrapper = document.createElement("div");
		debugWrapper.id = "debug";
		debugWrapper.onclick = function() {
			debugWrapper.innerHTML = "";
		}
		var p = document.getElementsByTagName("body")[0];
		p.appendChild(debugWrapper);
	}
	var debug = document.createElement("div");
	debug.className = "debug";
	debug.innerHTML = mixed;
	debugWrapper.appendChild(debug);
}

function rand() {
	return Math.random() * 9999;
}

/**
 *
 * Class that implements a Flickr Slideshow-Element
 * It provides functionality for loading the thumbimages via asynchronous (a)jax-calls
 * and visual effects such as sliding and blind up/down
 *
 * @author	Alex Buchgeher
 * created 	on 2007-07-12, 2007-11-30
 * @version	1.0.2	new version, cleanup, 
 * 	TODO: check/remove IE memoy-leaks
 *
 */
PhotogallerySlider = Class.create();
PhotogallerySlider.prototype = {
	/**
	 * Class Constructor
	 */
	initialize: function(sliderId, galleryId, galleryPid, secret, imgW, imgH, open) {
		try {
			if(!Rico) {
				alert("Rico Effects Library not found!");
				return;
			}
		} catch(e) {
			alert("Rico Effects Library not found!");
			return;
		}
		this.sliderId = sliderId;
		this.galleryId = galleryId;
		this.galleryPid = galleryPid;
		this.imgW = imgW;
		this.imgH = imgH;
		this.open = open;
		this.prefix = new String("tx-photogallery-pi1-flicker-");


		this.head = null;
		this.tail = null;
		this.headLoaded = false;
		this.tailLoaded = false;
		this.cursor = null;

		this.leftPointer = null;
		this.rightPointer = null;
		
		this.secretL = new String();
		this.secretR = new String();

		this.loadNextInProgress = false;
		this.loadPrevInProgress = false;

		this.slideInProgress = false;


		// setting relevant for rico and script.aculo.us library
		this.opt = {duration: 0.5};
		this.slideSteps = 20;
		this.slideMilliseconds = 50;
		this.sliderPos = 0; // 0 will we interpretated as null (fixed that problem in rico.js)
		this.sliderDist = imgW;
		Event.observe(window, "unload", this.cleanUp.bind(this));
		this.buildSlider(secret);
	},

	sendRequest: function(parameters, func) {
		var url = "index.php?eID=tx_photogallery_pi1_ajax";
		if(parameters != "") {
			parameters += "&";
		}
		parameters += "cHash="+rand();
		var options = {
			asynchronous: true,
			method: "get",
			requestHeaders: ['Pragma', 'no-cache', 'Cache-Control', 'must-revalidate'],
			parameters: parameters,
			onComplete: func
		//	on404: this.error404.bind(this),
		//	on403: this.error403.bind(this),
		//	onFailure: this.errorDefault.bind(this)
		};
		new Ajax.Request(url, options);
	},
	
	/**
	 * Builds the slider
	 * @return void
	 */
	buildSlider: function(secret) {
		this.toggleButton = document.getElementsByClassName(this.prefix + "header-toggle", this.sliderId)[0];
		var sliderWrapper = document.getElementsByClassName(this.prefix + "body-thumbnails", this.sliderId)[0];
		this.slider = document.getElementsByClassName(this.prefix + "body-thumbnails-slider", this.sliderId)[0];
		this.albuminfo = document.getElementsByClassName(this.prefix + "body-albuminfo", this.sliderId)[0];
		this.prevButton = document.getElementsByClassName(this.prefix + "body-slider-browser-prev", this.sliderId)[0];
		this.nextButton = document.getElementsByClassName(this.prefix + "body-slider-browser-next", this.sliderId)[0];
		this.moreButton = document.getElementsByClassName(this.prefix + "body-slider-browser-more", this.sliderId)[0];
		this.loadingbarNode = document.getElementsByClassName(this.prefix + "body-loadingbar", this.sliderId)[0];
		this.body = document.getElementsByClassName(this.prefix + "body", this.sliderId)[0];
		
		Event.observe(this.toggleButton, "click", this.toggle.bind(this));
		Event.observe(this.prevButton, "click", this.slidePrev.bind(this));
		Event.observe(this.nextButton, "click", this.slideNext.bind(this));
		this.moreButton.href = "index.php?id=" + this.galleryPid + "&tx_photogallery_pi1[galleryid]=" + this.galleryId;
		
		//sliderWrapper.style.width = new String(2 * this.imgW + "px");
		//sliderWrapper.style.height = new String(this.imgH + "px");
		
		
		this.slider.style.width = new String(3 * this.imgW + "px");
		this.slider.style.height = new String(this.imgH + "px");
		
		var params = "cmd=init&galleryId=" + this.galleryId + "&imgW=" + this.imgW + "&imgH=" + this.imgH + "&secret=" + secret;
		var func = this.procInitRequest.bind(this);
		this.loadingbar(true);
		this.sendRequest(params, func, "get");
	},

	procInitRequest: function(xhr) {
		var xml = xhr.responseXML;

		var size = xml.getElementsByTagName("gallery")[0].getAttribute("photos");
		this.albuminfo.innerHTML = size + " Photos";
		var images = xml.getElementsByTagName("image");
		this.head = images[0].getAttribute("imageid");
		this.tail = images[1].getAttribute("imageid");
		this.secretL = images[0].getAttribute("secret");
		this.secretR = images[1].getAttribute("secret");

		var builtImage1 = this.buildImage(images[0].getAttribute("imageurl"), images[0].getAttribute("filename"));
		var builtImage2 = this.buildImage(images[1].getAttribute("imageurl"), images[1].getAttribute("filename"));

		this.slider.appendChild(builtImage1);
		this.slider.appendChild(builtImage2);

		var dist = 0;
		dist = parseInt(this.getStyle(builtImage1, 'padding-left').replace(/px/, ''));
		dist += parseInt(this.getStyle(builtImage1, 'margin-right').replace(/px/, ''));
		dist += parseInt(this.getStyle(builtImage1, 'padding-right').replace(/px/, ''));
		dist += parseInt(this.getStyle(builtImage1, 'margin-left').replace(/px/, ''));

		this.sliderDist += dist*2;
		this.leftPointer = builtImage1;
		this.rightPointer = builtImage2;
		
		var margin = parseInt(this.getStyle(this.leftPointer, "margin-right").replace(/px/, ''));
		this.sliderDist += margin;
		this.loadingbar(false);
	},

	buildImage: function(imageurl, imageId) {
		var div = document.createElement("div");
		var a = document.createElement("a");
		var img = document.createElement("img");
		img.src = imageurl;
		img.style.width = this.imgW.toString() + "px";
		img.style.height = this.imgH.toString() + "px";
		a.href = "index.php?id=" + this.galleryPid + "&tx_photogallery_pi1[galleryid]=" + this.galleryId + "&tx_photogallery_pi1[imageid]=" + imageId;
		div.appendChild(a);
		a.appendChild(img);
		return div;
	},

	/**
	 * Whether to turn the loadingbar on or off
	 */
	loadingbar: function(show) {
		if(show) {
			this.loadingbarNode.style.display = "block";			
		} else {
			this.loadingbarNode.style.display = "none";
		}
	},

	/**
	 * Toggles (BlindUp/BlindDown) the item with css-id <code>this.id</code>
	 * @return void
	 */
	toggle: function() {
		if(this.open) {
			// new Effect.BlindUp(this.toggleID, this.opt); // buggy in stoopid ie
			//new Effect.SlideUp(this.body, this.opt);
			Element.toggle(this.body);
			this.toggleButton.className = this.prefix + "header-toggle-closed";
		} else {
			// new Effect.BlindDown(this.toggleID, this.opt);
			//new Effect.SlideDown(this.body, this.opt);
			Element.toggle(this.body);
			this.toggleButton.className = this.prefix + "header-toggle";
		}
		this.open = !this.open;
	},

	/**
	 * Returns the actual style of the given element
	 * @author robert nyman @see www.robertnyman.com
	 * @param object
	 * @param string
	 * @return string
	 */
	getStyle: function(oElm, strCssRule){    
		var strValue = "";
	    if(document.defaultView && document.defaultView.getComputedStyle){
	        strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
	    }
	    else if(oElm.currentStyle){
	        strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
	            return p1.toUpperCase();
	        });
	        strValue = oElm.currentStyle[strCssRule];
	    }
	    return strValue;
	},





	/**
	 * Loads the next photo and slides
	 * one step right
	 * @return void
	 */
	slideNext: function() {
		if(this.slideInProgress) {
			debug("slide in progress - next");
			return;
		}
		this.slideInProgress = true;
		if((this.rightPointer.nextSibling == null ||  this.rightPointer.nextSibling.nodeType == 3) && this.tailLoaded) {
			this.slideInProgress = false;
			return; // reached the tail, nothing to do
		} else if(this.rightPointer.nextSibling == null || this.rightPointer.nextSibling.nodeType == 3) { // load new image, then slide
			this.loadNext();
			return;
		} else { // nothing new to load, just slide
			this.leftPointer = this.rightPointer;
			this.rightPointer = this.rightPointer.nextSibling;		
		}
		this.sliderPos-= this.sliderDist;		
		this.slide();
	},

	/**
	 * Loads the next photo and slides
	 * one step left
	 * @return void
	 */
	slidePrev: function() {
		if(this.slideInProgress) {
			debug("slide in progress - prev");
			return;
		}
		this.slideInProgress = true;
		if((this.leftPointer.previousSibling == null || this.leftPointer.previousSibling.nodeType == 3) && this.headLoaded) {
			this.slideInProgress = false;
			return; // reached the head, do nothing
		} else if(this.leftPointer.previousSibling == null || this.leftPointer.previousSibling.nodeType == 3) { // load new image, then slide
			this.loadPrev();
			return;
		} else { // nothing new to load, just slide
			this.sliderPos+= this.sliderDist;
			this.rightPointer = this.leftPointer;
			this.leftPointer = this.leftPointer.previousSibling;
		}
		this.slide();
	},

	slide: function() {
		new Rico.Effect.Position(this.slider, parseInt(this.sliderPos), null, this.slideMilliseconds, this.slideSteps, {complete: this.slideComplete.bind(this)});
	},
	
	slideComplete: function(){
		this.slideInProgress = false;
	},



	/**
	 * Loads the next photo
	 * @return void
	 */
	loadNext: function() {
		if(this.loadNextInProgress) { return; }
		this.loadNextInProgress = true;
		this.loadingbar(true);
		var params = "cmd=getNext&galleryId=" + this.galleryId + "&uid=" + this.tail + "&imgW=" + this.imgW + "&imgH=" + this.imgH + "&secret=" + this.secretR;
		var func = this.procAppendRequest.bind(this);
		this.sendRequest(params, func, "get");
	},

	/**
	 * Loads the previous photo
	 * @return void
	 */
	loadPrev: function() {
		if(this.loadPrevInProgress) { return; }
		this.loadPrevInProgress = true;
		this.loadingbar(true);
		var params = "cmd=getPrev&galleryId=" + this.galleryId + "&uid=" + this.head + "&imgW=" + this.imgW + "&imgH=" + this.imgH + "&secret=" + this.secretL;
		var func = this.procInsertRequest.bind(this);
		this.sendRequest(params ,func, "get");
	},

	procAppendRequest: function(xhr) {
		this.processRequest(xhr, "append");
	},

	procInsertRequest: function(xhr) {
		this.processRequest(xhr, "insert");
	},
	
	/**
	 * Inserts the result of the Ajax response
	 */
	processRequest: function(xhr, cmd) {
		var xml = xhr.responseXML;
		var image = null;
		var imageNode;
		var imageUrl;
		var secret;
		var uid;
		try {
			imageNode = xml.getElementsByTagName("image")[0];
			imageUrl = imageNode.getAttribute("imageurl");
			secret = imageNode.getAttribute("secret");
			uid = imageNode.getAttribute("imageid");
		} catch(e) {
			imageUrl = false
		}
		if(!imageUrl) { // no more images
			image = document.createElement("div");
			var span = document.createElement("span");
			if(cmd == "append") {
				this.tailLoaded = true;
				span.appendChild(document.createTextNode("no more images (tail)"));
				image.setAttribute("class", "tx-photogallery-pi1-slider-nomoreimages-tail");
			} else {
				this.headLoaded = true;
				span.appendChild(document.createTextNode("no more images (head)"));
				image.setAttribute("class", "tx-photogallery-pi1-slider-nomoreimages-head");
			}
			image.appendChild(span);
		} else {
			switch(cmd) {
				case "append":
					this.tail = uid;
					break;
				case "insert":
					this.head = uid;
					break;
				default:
					break;
			}
			image = this.buildImage(imageUrl, imageNode.getAttribute("filename"));
		}

		switch(cmd) {
			case 'append':
				this.slider.appendChild(image);
				this.leftPointer = this.rightPointer;
				this.rightPointer = this.rightPointer.nextSibling;
				this.sliderPos-= this.sliderDist;
				this.secretR = secret;
				this.loadNextInProgress = false;
				break;
			case 'insert':
				this.slider.insertBefore(image, this.slider.getElementsByTagName('div')[0]);
				this.slider.style.left = ((this.sliderPos - this.sliderDist) + "px").toString();
				this.rightPointer = this.leftPointer;
				this.leftPointer = this.leftPointer.previousSibling;
				this.secretL = secret;
				this.loadPrevInProgress = false;
				break;
		}
		var width = parseInt(this.getStyle(this.slider, "width").replace(/px/, '')) + this.sliderDist;
		this.slider.style.width = width.toString() + "px";
		
		this.loadingbar(false);
		this.slide();
	},
	
	/**
	 * Cleanup func
	 */
	cleanUp: function() {
		
	}
}
