/**
 * The ExtendedImageCycle class is based on the ExtendedImageCycle class.
 * 
 * @param	Node
 * @param	Node
 * @param	Node
 * @param	Array of Array of String [optional]
 * 
 * The ExtendedImageCycle class extends upon and modifies the ExtendedImageCycle class in these regards:
 * - It adds an optional second image for every data set
 * - Instead of a caption with an associated style it uses a description,
 *   which may contain markup, in contrast to the plain-text caption.
 * - It utilizes more space, namely parts of the main text content area for the description and the title
 *
 * 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 ExtendedImageCycle(container, title, description, images) {
	this.container = container;
	for(i in this.container.childNodes)
		if (this.container.childNodes[i].tagName
		&&  this.container.childNodes[i].tagName.toLowerCase() == 'img') {
			if (this.image) {
				this.extra_image = this.container.childNodes[i];
				break;
			} else
				this.image = this.container.childNodes[i];
		}
	
	this.title = title;
	this.description = description;
	
	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.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.appendChild(this.back_button);
}

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

/**
 * Updates the array of images with the given array.
 *
 * @param	Array of Array of String
 *
 * @return	false if given object is not an array
 *
 * Expects an Array of Arrays, each of which contains in this order:
 * the image path, the title, the description, optionally the additional image path.
 */
ExtendedImageCycle.prototype.set_images = function(new_images) {
	if (is_array(new_images)) {
		this.images = [];
		for(i in new_images) {
			array = new_images[i];
			object = {};
			object.path = array[0];
			object.title = array[1];
			object.description = array[2];
			if (array[3])
				object.extra_path = array[3];
			this.images.push(object);
		}
		count_down = this.images.length;
		while (count_down-- > 0 && this.image_data().path != this.image.src)
			this.cycle_images_forth();
		this.update_image();
	} else {
		return false;
	}
}

/**
 * Updates the image and description elements with the current image data.
 */
ExtendedImageCycle.prototype.update_image = function() {
	data = this.image_data();
	this.image.src = data.path;
	this.title.innerHTML = data.title;
	this.description.innerHTML = data.description;
	this.extra_image.src = data.extra_path;
	if(data.extra_path)
		this.show_extra_image();
	else
		this.hide_extra_image();
}

/**
 * Returns the data for the current image.
 *
 * @return	Object
 */
ExtendedImageCycle.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.
 */
ExtendedImageCycle.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.
 */
ExtendedImageCycle.prototype.previous_image = function() {
	this.cycler.cycle_images_back();
	this.cycler.update_image();
}

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

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

/**
 * Makes the optional additional image visible.
 */
ExtendedImageCycle.prototype.show_extra_image = function() {
	this.extra_image.removeAttribute('style');
}

/**
 * Makes the optional additional image invisible.
 */
ExtendedImageCycle.prototype.hide_extra_image = function() {
	this.extra_image.setAttribute('style', 'display: none');
}

// 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);
	}
}

