Object.pop = function(obj, key) {
	if(typeof obj[key] != 'undefined') {
		var objClone = obj;
		var value = objClone[key];
		for(var i in objClone) {
			if(i == key) obj[i] = undefined;
			obj[i] = objClone[i];
		}
		
		return value;
	}
	
	return undefined;
};

var ImageSlide = Class.create({
	options: {
		//ajax
		Ajax: { url: '', method: '', parameters: '' },
		useAjax: false,
		
		//image options
		interval: 1,
		insertDescp: false,
		images: [],
		element: undefined,
		preloadImageStack: false,
		
		//events
		Events: {
			oncreate: null,
			ondisplayimage: null,
			onimagesloaded: null,
			onnextimage: null,
			onrestart: null,
			onidle: null
		}
	},
	imageStack: [],
	element: null,
	loadedImages: {},
	eventStack: {},
	currentImage: 0,
	interval: null,
	initialize: function() {
		if(arguments.length > 0)
			Object.extend(this.options, arguments[0]);
		else throw 'ImageSlide::no options given...';
		
		this._registerEvents(); //to observe them
		this._fireEvent('create');
		
		if(this.options.element && this.options.element.hide)
			this.element = this.options.element;
		else {
			var tmpElement = $(this.options.element);
			if(!tmpElement) 
				throw 'element not found! you have to pass an id or an element as option.element to ImageSlide...';
			this.element = tmpElement;
		}
		
		//start slideshow using the imagesloaded event
		this.observe('imagesloaded', this.start);
		this.keyEventListener = (function(event) {
			if(event.keyCode == Event.KEY_ESC) {
				this.stop();
				Event.stopObserving(document, 'keydown', this.keyEventListener);
			}
		}).bindAsEventListener(this);
		Event.observe(document, 'keydown', this.keyEventListener);
		
		//use ajax?
		if(this.options.useAjax == true) {
			this._initAjax();
			var _self = this;
			new Ajax.Request(this.ajaxURL, Object.extend(this.ajaxOptions, {
				onSuccess: _self._handleAjaxResponse.bind(_self)
			}));
		} else if(Object.isArray(this.options.images) && this.options.images.length) {
			this.insertImages(this.options.images);
		} else this._fireEvent('idle'); //nothing to do
		
		//register event-handler to stop this animation by blur
		Event.observe(window, 'blur', this.stop.bindAsEventListener(this));
		Event.observe(window, 'focus', this.start.bindAsEventListener(this));
	},
	
	_initAjax: function() {
		this.ajaxOptions = {};
		this.ajaxURL = Object.pop(this.options.Ajax, 'url');
		Object.extend(this.ajaxOptions, this.options.Ajax);
		
		//failed response
		this.ajaxOptions.onFailure = function() {
			alert('Images could not be loaded form response. Ajax-request failed!');
		};
		
		//failed code
		this.ajaxOptions.onException = function(ajaxBase, error) {
			throw error;
		};
	},
	
	_handleAjaxResponse: function(r) {
		if(!r.responseXML) throw 'ImageSlide::Ajax-result must be in XML';
		else if(!(root = r.responseXML.getElementsByTagName('images').item(0).getElementsByTagName('image'))) 
			throw 'ImageSlide::Ajax-responseXML is not valid';
		
		
		var images = [];
		for(var i = 0, to = root.length; i < to; i++)
			images.push(root.item(i).getAttribute('src'));
		
		this.insertImages(images);
	},
	
	_fireEvent: function(name) {
		if(typeof this.eventStack[name] != 'undefined') {
			$A(this.eventStack[name]).each(function(event) {
				event.call(this);
			}.bind(this));
		}
	},
	
	_registerEvents: function() {
		$H(this.options.Events).each(function(event) {
			if(Object.isFunction(event.value)) {
				var eventName = event.key;
				if(eventName.substr(0, 2).toLowerCase() == 'on')
					eventName = eventName.substr(2, eventName.length);
				
				if(!Object.isArray(this.eventStack[eventName]))
					this.eventStack[eventName] = [];
					
				this.eventStack[eventName].push(event.value);
			}
		}.bind(this));
	},
	
	observe: function(event, callback) {
		if(!Object.isFunction(callback)) 
			throw 'unexpected argument[1] (2), function expected!';
		
		if(event.substr(0, 2).toLowerCase() == 'on')
			event = event.substr(2, event.length);
			
		if(typeof this.eventStack[event] == 'undefined')
			this.eventStack[event] = [];
		
		this.eventStack[event].push(callback);
	},
	
	insertImages: function(stack) {
		$A(stack).each(function(image) {
			if(this.options.preloadImageStack) {
				var i = new Image();
				//to keep order, set preloadImageStack to false
				i.onload = function() { this.images.push(image); }.bind(this);
				i.src = image;
				this.loadedImages[image] = true;
			} else this.imageStack.push(image);
		}.bind(this));
		
		this._fireEvent('imagesloaded');
	},
	
	stop: function() {
		if(this.running != true) return;
		this.running = false;
		this.interval.stop();
	},
	
	start: function() {
		if(this.running == true) return;
		this.running = true;
		this.interval = new PeriodicalExecuter((function() {
			this._displayNextImage();
		}).bind(this), this.options.interval);
	},
	
	_isLoaded: function(src) {
		return !(typeof this.loadedImages[src] == 'undefined')
	},
	
	_displayNextImage: function() {
		if(this.currentImage == this.imageStack.length) 
			this.currentImage = 0;
		
		var image = this.imageStack[this.currentImage++];
		if(!this._isLoaded(image)) {
			var i = new Image();
			i.src = image;
			this.loadedImages[image] = true;
		}
		
		var newImage = new Element('img', { src: image }); //.setStyle(this.resizeImage(image));
		//newImage.setStyle('margin-top:' + ((this.element.offsetHeight - newImage.height) / 2) + 'px');
		if(typeof Effect != 'undefined') {
			var oldImage = this.element.getElementsByTagName('img')[0];
			var oldStyle = newImage.style.cssText;
			var _self = this;
			newImage.hide().setStyle('position:absolute;');
			//newImage.setStyle('top:' + (this.element.offsetTop) + 'px');
			
			if(Prototype.Browser.IE) {
				newImage.setStyle('margin-left:-380px;');
				if(!window.XMLHttpRequest) newImage.setStyle('margin-left:-382px;');
			} else newImage.setStyle('left:' + (this.element.offsetLeft) + 'px');
			
			this.element.appendChild(newImage);
			Effect.Appear(newImage, { duration:3, afterFinish: function() {
				_self.element.removeChild(oldImage);
				newImage.setStyle('position:static;top:0;z-index:0;margin-left:0;');
			}} );
		} else this.element.update(newImage);
	}
	
	/**
	* not longer needed, because all images have correct width and height
	*
	resizeImage: function(image) {
		var img = new Image();
		img.src = image;
		if(!this._isLoaded(image)) {
			img.onload = function() { this.loadedImages[image] = true; }.bind(this);
			return this.resizeImage(image);
		} else {
			var width = img.width;
			var height = img.height;
			var maxWidth = this.element.offsetWidth - 5;
			var maxHeight = this.element.offsetHeight - 5;
			
			if(width > maxWidth || height > maxHeight) {
				var div1 = maxWidth / width;
				var div2 = maxHeight / height;
				if(div1 < div2) {
					var returnWidth = maxWidth;
					var returnHeight = Math.round(height * div1);
				} else {
					var returnWidth = Math.round(width * div2);
					var returnHeight = maxHeight;
				}
			} else {
				var returnWidth = width;
				var returnHeight = height;
			}
			var returnWidth = 380; var returnHeight = img.height;
			return { width:returnWidth + 'px', height:returnHeight + 'px' };
		}		
	}
	*/
});


window.onload = function() { 
	var i = new ImageSlide({
		element: 'imageSlideBox',
		useAjax: true,
		Ajax: {
			url: 'images.php',
			method: 'get'
		},
		interval: 8
	}); 
};
