/**
 * The ImageCycle class cycles through a given set of images upon clicking the automatically generated buttons.
 * 
 * @param	Node
 * @param	Array	optional
 *
 * Expects the generated buttons to be positioned by CSS.
 * Buttons will be generated inside the given container node.
 * Buttons get the classes 'next_image' and 'previous_image'.
 * Generates caption element inside container node.
 *
 * Requires DOM functions!
 * Almost no error handling throughout!!
 */
function ImageCycle(container, images) {
	this.container = container;
	for(i in this.container.childNodes)
		if (this.container.childNodes[i].tagName
		&&  this.container.childNodes[i].tagName.toLowerCase() == 'img') {
				this.image = this.container.childNodes[i];
			break;
		}
	
	this.caption = document.createElement('p');
	this.caption.className = 'caption';
	this.container.appendChild(this.caption);
	
	this.images = [];
	this.set_images(images);
	
	this.forth_button = document.createElement('a');
	this.forth_button.cycler = this;
	this.forth_button.onclick = this.next_image;
	image = document.createElement('img');
	image.src = '/images/next_image.png';
	image.alt = this.next_image_label;
	this.forth_button.appendChild(image);
	this.forth_button.className = 'next_image';
	this.container.parentNode.appendChild(this.forth_button);
	
	this.back_button = document.createElement('a');
	this.back_button.cycler = this;
	this.back_button.onclick = this.previous_image;
	image = document.createElement('img');
	image.src = '/images/previous_image.png';
	image.alt = this.previous_image_label;
	this.back_button.appendChild(image);
	this.back_button.className = 'previous_image';
	this.container.parentNode.appendChild(this.back_button);
}

// global defaults
ImageCycle.prototype.next_image_label = 'nächstes Bild';
ImageCycle.prototype.previous_image_label = 'vorheriges Bild';

/**
 * Updates the array of images with the given array.
 *
 * @param	Array
 *
 * @return	false if given object is not an array
 *
 * Expects an Array of Arrays, each of which contains
 * first the image path, then the title, optionally the caption.
 */
ImageCycle.prototype.set_images = function(new_images) {
	if (is_array(new_images)) {
		this.images = [];
		for(i in new_images) {
			array = new_images[i];
			object = {};
			object.source = array[0];
			object.title = array[1];
			if (array[2]) {
				caption_data = /^(\s*\[(.+?)\]\s*)?(.*)/.exec(array[2]);
				object.caption = caption_data[3];
				object.caption_style = caption_data[2] ? caption_data[2] : 'empty';
			} else {
				object.caption = '';
				object.caption_style = 'empty';
			}
			this.images.push(object);
		}
		count_down = this.images.length;
		while (count_down-- > 0 && this.image_data().source != this.image.src)
			this.cycle_images_forth();
		this.update_image();
	} else {
		return false;
	}
}

/**
 * Updates the image and caption elements with the current image data.
 */
ImageCycle.prototype.update_image = function() {
	this.image.src = this.image_data().source;
	this.image.alt = this.image_data().title;
	this.caption.innerHTML = this.image_data().caption;
	this.caption.className = 'caption '+this.image_data().caption_style;
}

/**
 * Returns the data for the current image.
 *
 * @return	Object
 */
ImageCycle.prototype.image_data = function() {
	return this.images[0];
}

/**
 * Tells the cycling object to advance by one image.
 *
 * Is automatically added to the generated next-button,
 * expects to be called from there.
 */
ImageCycle.prototype.next_image = function() {
	this.cycler.cycle_images_forth();
	this.cycler.update_image();
}

/**
 * Tells the cycling object to regress by one image.
 *
 * Is automatically added to the generated previous-button,
 * expects to be called from there.
 */
ImageCycle.prototype.previous_image = function() {
	this.cycler.cycle_images_back();
	this.cycler.update_image();
}

/**
 * Cycles the images array, putting the first element to the rear.
 */
ImageCycle.prototype.cycle_images_forth = function() {
	this.images.push(this.images.shift());
}

/**
 * Cycles the images array, getting the last element to the front.
 */
ImageCycle.prototype.cycle_images_back = function() {
	this.images.unshift(this.images.pop());
}

// Helper functions not directly part of the class

/**
 * Checks whether the given object is an Array.
 *
 * @param	Object
 *
 * @return	true if given object is an Array, false otherwise
 */
function is_array(object) {
	try {
		return object instanceof Array;
	} catch (error) {
		// if the client doesn't support the instanceof operator this has the same result, albeit at a lower speed
		return (obj.constructor.toString().indexOf("Array") != -1);
	}
}

