// Contains classes that control the carousel on the home page.

/** A class to contain information for a carousel item.
 */
function CarouselDataItem (initObj) {
	this.imageSrc = '';
	this.imageDescription = '';
	this.imageLink = '';
	this.text = '';
	
	this.anchorWrapper = null; // This is a reference to an object that wraps an anchor Element that when clicked causes the item to be displayed.
	
	try {
		this.imageSrc = initObj.imageSrc;
		this.imageDescription = initObj.imageDescription;
		this.imageLink = initObj.imageLink;
		this.text = initObj.text;
	}
	catch (e) {
		alert(e);
	}
}

/** Encapsulates CarouselDataItems and related presentation logic.
 *
 */
function CarouselCollection () {
	this.items = new Array();
	this.pointer = 0;
	this.carouselIDPrefix = "carousel";
	
	// Add an item to the carousel.
	this.add = function (dataItem) {
		this.items.push(dataItem);
	}
	
	/** Set the prefix for the id of scripted elements in the carousel. (?_imageLink, ?_itemLinks, ?_text) These provide hooks in the HTML into which content is inserted.
	 *  Overides default "carousel".
	 *  @param prefix String
	 *  @return null
	 */
	this.set_carouselIDPrefix = function (prefix) {
		this.carouselIDPrefix = prefix;
		return null;
	}
	
	// Treat as private.
	/** Set internal pointer to a random position.
	 *  @return null
	 */
	this.randomizePointer = function () {
		this.pointer = Math.floor(Math.random() * this.items.length);
		return null;
	}
	
	
	/** Determine the number of items in the carousel.
	 *  @return int
	 */
	this.getLength = function () {
		return this.items.length;
	}
	
 
	/** Displays the content of a carousel item. Treat as private.
	 *  @return null
	 */
	this.display = function () {
		try {
			$(this.carouselIDPrefix + '_image').writeAttribute(
				{
					'src': this.items[this.pointer].imageSrc,
					'alt': this.items[this.pointer].imageDescription
				}
			);
			$(this.carouselIDPrefix + '_text').innerHTML = this.items[this.pointer].text
			
			if (this.items[this.pointer].imageLink != "") {
				$(this.carouselIDPrefix + '_imageLink').writeAttribute(
					{ 
						'href': this.items[this.pointer].imageLink
					}
				);
				
				$(this.carouselIDPrefix +  '_imageLink').removeClassName('cursorDefault');
				$(this.carouselIDPrefix +  '_imageLink').addClassName('cursorPointer');
				
				//console.log('I linked.');
			}
			else {
				$(this.carouselIDPrefix + '_imageLink').writeAttribute(
					{
						'href':  "javascript:void(0);"
					}
				);

				$(this.carouselIDPrefix +  '_imageLink').removeClassName('cursorPointer');
				$(this.carouselIDPrefix +  '_imageLink').addClassName('cursorDefault');
				
				//console.log("I didn't link.");
			}
		}
		catch (e) {
			//console.log(e);
		}

		return null;
	}
	
	
	/** Displays the item for the given index.
	 *  @param index int
	 *  @return null
	 */
	this.show = function (index) {
		this.items[this.pointer].anchorWrapper.makeNormal();
		
		this.pointer = index;
		this.display();

		this.items[this.pointer].anchorWrapper.makeActive();
		
		return null;
	}
	
	
	/** Changes the displayed item to the next item in the collection, unless it is the last, in which case it rewinds to the first.
	 *  @return null
	 */
	this.showNext = function () {

		var newPointer = 0;
		if (this.pointer + 1 == this.items.length) newPointer = 0;
		else newPointer = this.pointer + 1;
		
		this.show(newPointer);
		
		return null;
	}
	
	this.showPrevious = function () {

		var newPointer = 0;
		if (this.pointer == 0 ) newPointer = this.items.length -1;
		else newPointer = this.pointer - 1;
		
		this.show(newPointer);
		
		return null;
	}
	
	/** Initialize the display of the carousel.
	 *  @return null
	 */
	this.init = function () {
		// Set the internal pointer of the carousel to a random item.
		this.randomizePointer();


		// Create item arrows and links and bind click events.
		var leftArrow = Element('a', {href: "javascript:void(0);"}).update("&laquo;");
		Event.observe(leftArrow, 'click', this.showPrevious.bind(this));
		
		
		$(this.carouselIDPrefix + '_itemLinks').insert('&#160;');
		
		$(this.carouselIDPrefix + '_itemLinks').insert(leftArrow);
		for (var i = 0; i < this.items.length; i++) {
			var numberLink = Element('a', {href: "javascript:void(0);"}).update(i + 1); // Creates the link for the item. Sets the text value to one more than the index in the collection.
			Event.observe(numberLink, 'click', this.show.bind(this, i));
			this.items[i].anchorWrapper = new AnchorWrapper(numberLink);
			
			$(this.carouselIDPrefix + '_itemLinks').insert(numberLink);
			$(this.carouselIDPrefix + '_itemLinks').insert('&#160;');
		}

		var rightArrow = Element('a', {href: "javascript:void(0);"}).update("&raquo;");
		Event.observe(rightArrow, 'click', this.showNext.bind(this));

		$(this.carouselIDPrefix + '_itemLinks').insert(rightArrow);


		// Show the initial item.
		this.items[this.pointer].anchorWrapper.makeActive();
		this.display();
		
		return null;
	}
	
}


// This Class wraps an anchor, stores it's default style info, and defines methods that provide effect.
function AnchorWrapper (anchorElement) {
	this.anchor = anchorElement;
	this.defaultStyle = Object.clone(anchorElement.style);
	
	this.makeNormal = function () {
		this.anchor.style.color = this.defaultStyle.color;
		this.anchor.style.textDecoration = this.defaultStyle.textDecoration;
		this.anchor.style.fontWeight = this.defaultStyle.fontWeight;
	}
	
	this.makeActive = function () {
		this.anchor.style.color = "#000000";
		this.anchor.style.textDecoration = "none";
		this.anchor.style.fontWeight = "bold";
	}
}

/** Assign the function on window or DOM load to initialize a carousel.
 *  @param event
 *  @param itemPrefix (optional) - The prefix for the id of carousel item data. Naming convention is itemPrefixn where n is an integer equal to or greater than 1. Defaults to "carouselItem_". I like to use the underscore at the end of the prefix before the number as it is easier to read. It is not required, however.
 *  @param itemCount - Name of the element containing the count of items.
 *	@param carouselIDPrefix - Yes, the 'D' is capitalized, so shoot me. If not null, the value is passed to an instantiated CarouselCollection.set_carouselIDPrefix(). (See the comments for that method.) Otherwise, the default "carousel" is used.
 *  @return CarourselCollection - A reference to the instance of the carousel created by calling this function. Returned value can be used for additional customization.
 */
 function buildCarouselOnLoad (event, itemPrefix, itemCountId, carouselIDPrefix) {
	if (itemPrefix == null) itemPrefix = "carouselItem_";
	if (itemCountId == null) itemCountId = 'carouselItemsCount';
	
	var carousel = new CarouselCollection ();
	
	var carouselItemsStartPosition = 1; // XSLT counts from 1, NOT 0
	var carouselItemsCount = parseInt($(itemCountId).innerHTML);
	//console.log("Number of items: " + carouselItemsCount);
	if (typeof carouselItemsCount == 'number' && isFinite(carouselItemsCount)) {
		//console.log("Item count passed type checking.");
		for (i = carouselItemsStartPosition; i <= carouselItemsCount; i++) {
			if ($(itemPrefix + i)) {	
				carousel.add(new CarouselDataItem (
					{
						imageSrc: $$('#' + itemPrefix + i + ' div.imageURL')[0].innerHTML.unescapeHTML(),
						imageLink: $$('#' + itemPrefix + i + ' div.imageLink')[0].innerHTML.unescapeHTML(),
						imageDescription: $$('#' + itemPrefix + i + ' div.imageDescription')[0].innerHTML,
						text: $$('#' + itemPrefix + i + ' div.itemText')[0].innerHTML
					}
				)); 
			}	
		}
	}
	else {
		console.log('Carousel item count is not a number. Check the XSLT.');
	}
	
	// Set the prefix for carousel ids if necessary.
	if (carouselIDPrefix != null) {
		carousel.set_carouselIDPrefix(carouselIDPrefix);
	}
	
	carousel.init();	
	return carousel;
}
