///	<summary>Enum ArrowDisplay<br>
///	Contains constants that will be used to determine when to display scroller arrows.
function ArrowDisplay() {}
ArrowDisplay.ALWAYS = 0;					// Arrows will always display
ArrowDisplay.FORCED_EXPANSION = 1;			// Arrows will only display if there are more items than displayed items
ArrowDisplay.AT_LIMITS = 2;					// Arrows will only display if we've reached either of the bounds of the items collection
ArrowDisplay.NEVER = 3;						// Arrows will never display

///	<summary>Class Scroller<br>
///	Abstract class that houses the logic to control a javascript scroller.  References to objects that inherit from this object should be obtained through the static method
///	<c>Scroller.GetScroller</c></summary>
///	<remarks>May want to throw in image preloader in here</remarks>
function Scroller() {
	// =========
	// Constants
	// =========
	
	this.MIN_ITEMS_FOR_RENDER = 1;
	
	// =================
	// Protected variables
	// =================
	
	this.name					= "scroller";					// Name of html element id to write scroller to
	this.start					= 0;							// Index of starting item to display
	this.maxItems				= 5;							// Max number of items to display
	this.initialSize			= 0;							// Initial size of items array
	this.items					= null;							// Array to store items to scroll
	this.itemsDisplayed			= 0;							// Internal counter indicate when we've reached the limit of items to display
	this.backArrow				= null;							// FPImage object
	this.forwardArrow			= null;							// FPImage object
	this.width					= "100%";						// Width of main table
	this.orientation			= "Horizontal";					// Orientation to display scroller in
	this.horizontalCellWidth	= 0;							// Width of item cell for Horizontal scroller
	this.verticalCellWidth		= 0;							// Width of item cell for Vertical scroller
	this.cellWidth				= this.horizontalCellWidth;		// Width of main scroller cells
	this.bgcolor				= "#FFFFFF";					// Bgcolor of main table
	this.firstRender			= true;							// Indicates if we are rendering the Scroller for the first time to aid in the Render() method logic
	this.verticalSpace			= 10;							// Space between rows for Vertical style scroller
	this.additionalSpacing		= 0;							// Spacing added to non-product cells ex: spacers between arrows
	this.site					= "us";							// Indicates site, used for pathing
	this.arrowDisplay			= ArrowDisplay.FORCED_EXPANSION;			// Indicates how arrows display will be determined
	this.cellAlignment			= "center";						// Cell alignment
	

	
	// =================
	// Protected Methods
	// =================
	
	///	<summary>Set the cell alignment property</summary>
	this.SetCellAlignment = function(value)
	{
		this.cellAlignment = value;
	}
	
	///	<summary>Sets the size of the items array if known ahead of time.</summary>
	this.SetSize = function(size) {
		this.initialSize = size;
	}
	
	///	<summary>Initializes the item array.</summary>
	this.Init = function() {
		this.items = new Array(this.initialSize);
	}
	
	///	<summary>Generates the html for <c>Scroller</c> cells.  Wraps in tr tags if displaying vertically.</summary>
	/// <param name="element"><c>string</c> html of cell.</param>
	/// <returns><c>string</c> of cell html</returns>
	this.FormatElement = function(element, tagPosition) {
		var html = "";
		
				// Wrap in row
		if (this.orientation == "Vertical") {
			html = "<tr>" + element + "</tr>"
		} else {
					// Determine if a row tags are needed
			if (tagPosition == null) {
				html = element;
			} else if (tagPosition <= 0) {
				html = "<tr>" + element;
			} else if (tagPosition > 0) {
				html = element + "</tr>";
			}
		}
		
		return html;
	}
	
	///	<summary>Generates the html for the <c>Scroller</c>.</summary>
	/// <returns><c>string</c> of <c>Scroller</c> html</returns>
	this.GetHtml = function() {
		var html = "";
		
				// Generate html only if there are items for scroller
		if (this.items.length >= this.MIN_ITEMS_FOR_RENDER) {
			html += "<table border=\"0\" width=\"" + this.width + "\" bgcolor=\"" + this.bgcolor + "\" cellpadding=\"0\" cellspacing=\"0\">";
			
			if (this.CheckArrowDisplay(this.start)) {
				html += this.FormatElement("<td align=\"right\"><a href=\"javascript: " + this.name + ".Scroll(-1);\">" + this.backArrow.html + "</a></td>");		// Back link
			}
			
			html += this.GetCellsHtml(this.start, this.items.length) +		// Items after start item
					this.GetCellsHtml(0, this.start);		// Items before start item
			
			if (this.CheckArrowDisplay(this.start)) {
				html += this.FormatElement("<td><a href=\"javascript: " + this.name + ".Scroll(1);\">" + this.forwardArrow.html + "</a></td>");		// Forward link
			}
			
			html += "</table>";
		}
		
		return html;
	}
	
	///	<summary>Generates the html for the all cells in the given range</summary>
	/// <param name="begin"><c>int</c> starting index of <c>items</c>.</param>
	/// <param name="end"><c>int</c> ending index of <c>items</c>.</param>
	/// <returns><c>string</c> html of cells in the given range</returns>
	this.GetCellsHtml = function(begin, end) {
		var html = "";
		
				// Loop items array for given bounds and retrieve the cell html
		for (i = begin; i < end; i++) {
					// Only display desired number of items
			if (this.itemsDisplayed >= this.maxItems) {
				break;
			}
			
					// Wrap in row
			if (this.orientation == "Vertical") {
				html += this.FormatElement(this.GetCellHtml(i));
				
						// Add spacer between rows
				if (this.verticalSpace > 0 && this.itemsDisplayed < (this.maxItems - 1)) {
					html += this.FormatElement("<td><img src=\"/img/s.gif\" width=\"1\" height=\"" + this.verticalSpace + "\" border=\"0\"></td>");
				}
					// Default (Horizontal)
			} else {
				html += this.GetCellHtml(i);
			}
			
			this.itemsDisplayed++;
		}
		
		return html;
	}
	
	///	<summary>Generates the html for the <c>Scroller</c> cells.</summary>
	/// <param name="i"><c>int</c> index of <c>items</c> to get html for.</param>
	///	<remarks>Abstract method that must defined in inheriting class</remarks>
	this.GetCellHtml = function(i) {
		
	}
	
	// ==============
	// Public Methods
	// ==============
	
	///	<summary>Returns the list of items.</summary>
	/// <returns><c>array</c> of items</returns>
	this.Items = function() {
		return this.items;
	}
	
	///	<summary>Sets the name of the <c>Scroller</c> to allow for multiple <c>Scroller</c> objects. Used to dynamically call functions and as 
	///	the id of the html element that the <c>Scroller</c> gets rendered to.</summary>
	/// <param name="value"><c>string</c> name of <c>Scroller</c>.</param>
	this.SetName = function(value) {
		this.name = value;
	}
	
	///	<summary>Sets the starting index of items to display.</summary>
	/// <param name="value"><c>int</c> index of the first item to display.</param>
	this.SetInitialItem = function(value) {
		if (!isNaN(value)) {
			if (value > 0 && value < this.items.length) {
				this.start = value;
			}
		}
	}
	
	///	<summary>Sets the maximum number of items to display.</summary>
	/// <param name="value"><c>int</c> maximum number of items to display.</param>
	this.SetMaxItems = function(value) {
		if (!isNaN(value)) {
			if (value > 0) {
				this.maxItems = value;
			}
		}
	}
	
	///	<summary>Sets the width of the main table.</summary>
	/// <param name="value"><c>int</c> width of the <c>Scroller</c>.</param>
	this.SetWidth = function(value) {
		this.width = value;
	}
	
	///	<summary>Sets the orientation of the scroller (vertical, horizontal default).</summary>
	/// <param name="value"><c>string</c> orientation of display.</param>
	///	<remarks>Possible values: Horizontal (default), Vertical</remarks>
	this.SetOrientation = function(value) {
		this.orientation = value;
	}
	
	///	<summary>Sets the bgcolor property of the <c>Scroller</c>.</summary>
	/// <param name="value"><c>string</c> bgcolor of <c>Scroller</c>.</param>
	this.SetBgcolor = function(value) {
		this.bgcolor = value;
	}
	
	///	<summary>Sets the space between rows of a vertical style <c>Scroller</c></summary>
	/// <param name="value"><c>int</c> number of pixels.</param>
	this.SetVerticalSpace = function(value) {
		this.verticalSpace =  value;
	}
	
	///	<summary>Gets the site</summary>
	/// <returns><c>string</c> site code</returns>
	this.GetSite = function() {
		return this.site;
	}
	///	<summary>Sets the site</summary>
	/// <param name="value"><c>string</c> site code.</param>
	this.SetSite = function(value) {
		this.site = value;
	}
	
	this.SetAdditionalSpacing = function(value) {
		this.additionalSpacing = value;
	}
	
	this.SetArrowDisplay = function(arrowEnumVal) {
		this.arrowDisplay = arrowEnumVal;
	}
	
	///	<summary>Sets the scroller arrows</summary>
	/// <param name="imgName"><c>string</c> name of arrow.  Possible values: back, forward</param>
	/// <param name="img"><c>EImage</c> object.</param>
	this.SetArrow = function(imgName, img) {
		switch(imgName) {
			case "back":
				this.backArrow = img;
				break;
			case "forward":
				this.forwardArrow = img;
				break;
		}
	}
	
	///	<summary>Pushes an <c>item</c> to the <c>items</c> array</summary>
	/// <param name="item"><c>object</c> item to be added to the <c>items</c> array</param>
	/// modified 10/4/04 - some mac versions don't support array.push?
	this.AddItem = function(item) {
		this.SetItem(item, this.items.length);
	}
	
	///	<summary>Sets the value of the <c>items</c> array at position <c>pos</c> to <c>item</c></summary>
	/// <param name="item"><c>object</c> item to be added to the <c>items</c> array</param>
	/// <param name="pos"><c>int</c> position of <c>items</c> array to add the item to</param>
	this.SetItem = function(item, pos) {
		this.items[pos] = item;
	}
	
	///	<summary>Updates the width of item cells</summary>
	this.UpdateWidth = function() {
		var cellWidthDivisor = (this.items.length < this.maxItems) ? this.maxItems : this.maxItems;
		
				// Update display settings
		this.horizontalCellWidth = Math.floor((isNaN(this.width)) ? 100 / (Math.min(this.maxItems, this.items.length)) + "%" : (this.width - (this.backArrow.width + this.forwardArrow.width + this.additionalSpacing)) / cellWidthDivisor);
		this.verticalCellWidth = this.width;
		this.cellWidth = (this.orientation == "Horizontal") ? this.horizontalCellWidth : this.verticalCellWidth;
	}

	///	<summary>Writes the <c>Scroller</c> html to the screen.</summary>
	this.Render = function() {
		this.UpdateWidth();
		
				// Write Scroller to screen
		if (this.firstRender) {		// Initial display
			this.firstRender = false;
			document.write(this.GetHtml());
		} else {
			document.getElementById(this.name).innerHTML = this.GetHtml();
		}
	}
	
	///	<summary>Moves the <c>Scroller</c> items in the given <c>direction</c></summary>
	/// <param name="direction"><c>int</c> indicates which way to scroll items</param>
	this.Scroll = function(direction) {
		
				// Increment/decrement starting item index
		if (direction > 0) {
			this.start++;
		} else {
			this.start--;
		}
		
				// Bound checks for the starting item index
		if (this.start > this.items.length) {
			this.start = 1;
		} else if (this.start < 0) {
			this.start = this.items.length - 1;
		}
		
		this.itemsDisplayed = 0;		// Reset control value
		this.Render();
	}
	
	this.CheckArrowDisplay = function (index) {
		var	returnVal	= false;
		
		switch (this.arrowDisplay) {
			case ArrowDisplay.ALWAYS:
				returnVal = true;
				break;
			case ArrowDisplay.FORCED_EXPANSION:
				if (this.items.length > this.maxItems) {
					returnVal = true;
				}
				break;
			case ArrowDisplay.AT_LIMITS:
				break;
			case ArrowDisplay.NEVER:
				returnVal = false;
		}
		
		return returnVal;
	}
}

Scroller.Type = "Product";		// Default value

///	<summary>Static method to dynamically instantiate a new <c>Scroller</c></summary>
/// <param name="jsClassName">Name of the <c>Scroller</c> class we want to instantiate</param>
/// <returns><c>Scroller</c> object</returns>
/// modified 10/8/2004: changed the parameter this fuction accepts to allow multiple types of scrollers on the same page.
Scroller.GetScroller = function(jsClassName) {
	var scroller = null;
	
			// Create an instance of the scroller class specified by jsClassName. Ex: new InteractvScroller
			// If this fails, create default scroller based on type that was set (default is ProductScroller)
	try {
		scroller = eval("new " + jsClassName + "();")
	} catch (e) {
		scroller = eval("new " + Scroller.Type + "Scroller();");
	}
	
	return scroller;
}

///	<summary>Creates a spacer image</summary>
/// <param name="width"><c>int</c> width of image.</param>
/// <param name="height"><c>int</c> height of image.</param>
/// <returns><c>FPImage</c> object</returns>
Scroller.GetSpacer = function(width, height) {
	return new FPImage("", "/img/spacer.gif", "", width, height, "", 0, false);
}