// JavaScript Document

	function isArray(obj) {
	   if (obj.constructor.toString().indexOf("Array") == -1)
		  return false;
	   else
		  return true;
	}
	
	OOP_extend = function(subClass, baseClass) {
       function inheritance() {}
	   inheritance.prototype = baseClass.prototype;
	
	   subClass.prototype = new inheritance();
	   subClass.prototype.constructor = subClass;
	   //subClass.parent = baseClass;
	   subClass.base = baseClass.prototype;
	}

	/************ Begin: class Product ************/
	
	// ---- Product constructor ----
	// elContainerId:     the id attr assigned to the element containing
	//				      our product. the class property will be changed
	//				      depending on whether it's selected or no.
	// elQtyId:		      the id attr assigned to the element with the 
	//				      quantity of the item (TODO: change for radios,...)
	// title:		      the name of the product
	// price:		      the price of the product. used as a base price if options
	//				      is specified; set to 0.0 if only to use option list.
	// [elOptionsId]:     the id attr assigned to the option list.
	// [options]:	      a list of the various options in form of an array, containing
	//				      associative arrays of the form { name: <option name>, price: <option price> } .
	//				      the indices of the options array must correspond to the indices
	//				      on the list specified by elOptionsId
	//				      note that <option price> is added on to the base price.
	//				      For example:
	//				      options = new Array(
	// 										  { "name": "Option 1", "price": 20.00 },
	//  									  { "name": "Option 2", "price": 15.00 },
	//										  { "name": "Option 3", "price": 8.00 }
	//							    );
	//				  
	function Product( elContainerId, title, price, elOptionsId, options ) {
	
		// verify container (div,span,td,whatever) exists.
		this.elContainer = document.getElementById(elContainerId);
		if ( !this.elContainer )
			throw "Could not locate container for '"+title+"'";
			
		// check is price is a valid decimal quantity.
		if ( price == parseFloat(price) )
			this.price = price;
		else
			throw "'"+price+"' is not a number.";
		
		
		if ( elOptionsId != null ) {
			this.elOptions = document.getElementById(elOptionsId);
			if ( !this.elOptions )
				throw "Could not locate options input for '"+title+"'";
		
			if ( !isArray(options) || options.length == 0 )
				throw "Option list is missing or empty for '"+title+"'";
			this.options = options;
		}
	
		
			
		this.id = elContainerId;
		this.title = title;
		this.baseClass = this.elContainer.className;
		
		return this;
	}
	
	// Unfortunately, javascript doesn't natively support classes.
	// this is a workaround.

	// ---- Product method: setHighlight()
	Product.prototype.setHighlight = function( newClass ) {
		this.elContainer.className = this.baseClass ? this.baseClass + ' ' + newClass : newClass;
	}
	
	// ---- Product method: getPrice()
	Product.prototype.getPrice = function() {
		
		if ( this.options != null ) {
			// if options are specified, calculate the price
			// based on the selected option.
			var selectedIdx = this.elOptions.selectedIndex;
			//alert(this.elOptions.options[0].text);
			return this.price + this.options[selectedIdx].price;
		}
		else
			return this.price;
	}

	// ---- Product method: getOption()
	// TODO: Allow more than 1 option.
	Product.prototype.getOption = function() {

		if ( this.options != null ) {
			var selectedIdx = this.elOptions.selectedIndex;
			return this.options[selectedIdx].name;
		}
		else
			return null;

	}
	
	// ---- Product method: eventQtyChange()
	Product.prototype.eventQtyChange = function() {
		// check if quantity if valid...
	}
	
	// ---- Product method: eventOptionChange()
	Product.prototype.eventOptionChange = function() {
		
	}
	
	/************ End: class Product ************/
	
	
	/************ Begin: class RelatedProduct extends Product ************/
	
	function RelatedProduct ( elContainerId, elQtyId, title, price, elOptionsId, options ) {
		RelatedProduct.base.constructor.call( this, elContainerId, title, price, elOptionsId, options );
	
		// we need access to the form input that controls qty.
		this.elQty = document.getElementById(elQtyId);
		if ( !this.elQty )
			throw "Could not locate quantity input for '"+title+"'";
			
	}
	OOP_extend( RelatedProduct, Product );
	
	// ---- RelatedProduct method: getQty()
	RelatedProduct.prototype.getQty = function() {
		return this.elQty.value;
	}

	// ---- RelatedProduct method: resetQty()
	RelatedProduct.prototype.resetQty = function() {
		this.elQty.value = '0';
	}
	
	// ---- RelatedProduct method: forceQty()
	RelatedProduct.prototype.forceQty = function() {
		this.elQty.value = '1';
	}
	
	/************ End: class RelatedProduct ************/
	
	
	/************ Begin: class ReqProduct extends Product ************/
	
	function ReqProduct ( elContainerId, elQtyId, title, price, elOptionsId, options ) {
		RelatedProduct.base.constructor.call( this, elContainerId, title, price, elOptionsId, options );
	
		// we need access to the form input that controls qty.
		this.elQty = document.getElementById(elQtyId);
		if ( !this.elQty )
			throw "Could not locate quantity box for '"+title+"'";
			
	}
	OOP_extend( ReqProduct, Product );
	
	// ---- ReqProduct method: getQty()
	ReqProduct.prototype.getQty = function() {
		return this.elQty.checked ? 1 : 0;
	}

	// ---- ReqProduct method: resetQty()
	ReqProduct.prototype.resetQty = function( ) {
		this.elQty.checked = false;
	}	

	// ---- ReqProduct method: forceQty()
	ReqProduct.prototype.forceQty = function( ) {
		this.elQty.checked = true;
	}
	
	/************ End: class RelatedProduct ************/
	
	
	/************ End: class PController ************/
	
	function PController( elSummaryId, classDefault ) {
		this.elSummary = document.getElementById(elSummaryId);
		if ( !this.elSummary )
			throw "Could not locate '"+elSummaryId+"'";
			
		this.products = new Object(); // so we can store as an associate array.
		this.listHl = new Array();
		this.classDefault = classDefault;
		//this.classHlOff = classHlOff;
	}
	
	
	// ---- PController method: addProduct()
	PController.prototype.addProduct = function(product) {
		this.products[product.id] = product;
	}
	
	// ---- PController method: updateSummary()
	PController.prototype.updateSummary = function() {
		var productQty;
		var total = 0.0;

		var summary = '<table>'
				+ '<tr>'
				    + '<th>Item</th>'
				    + '<th>Price</th>'
				    + '<th>Quantity</th>'
				+ '</tr>';
		
		for( var id in this.products ) {
			product = this.products[id];
			productPrice = product.getPrice();
			productQty = product.getQty();
			productOption = product.getOption();

			if ( productPrice.toFixed )
				productPrice = productPrice.toFixed(2);
			
			if ( productQty > 0 ) {
				total += productPrice * productQty;
				summary += '<tr>'
				  		+ '<td class="summary-prod-info"><span class="summary-prod-title">'+product.title+'</span>'+ ( (productOption != null) ? '<span class="summary-prod-attr">'+productOption+'</span>' : '' ) +'</td>'
				  		+ '<td class="summary-prod-price">$'+productPrice+'</td>'
				  		+ '<td class="summary-prod-qty">'+productQty+'</td>' +
					   '</tr>';
			}
		}
		
		summary += '<tr><td class="summary-total-title">Sub-Total:</td>'
			     + '<td class="summary-total-price">$'+ ( total.toFixed ? total.toFixed(2) : total )+'</td></table>';
		this.elSummary.innerHTML = summary;
	}
	
	// ---- PController method: reset()
	PController.prototype.reset = function() {
		// unhighlight previously highlighted Product()s,
		// set qty = 0
		// then clear the highlight list.
		for ( i = 0; i < this.listHl.length; i++ ) {
			this.listHl[i].setHighlight(this.classDefault);
			this.listHl[i].resetQty();	
		}
		this.listHl = new Array();
	}

	// ---- PController method: select()
	PController.prototype.select = function() { // params: newClass, id1,id2,...
		var args = PController.prototype.select.arguments;
		var i, product;
		var newClass = args[0];
		
		// clear highlights
		this.reset();

		// go through our 'select' list, highlight, and set qty = 1.
		for ( i = 1; i < args.length; i++ ) {
			product = this.products[args[i]];
			product.setHighlight(newClass);
			product.forceQty();
			this.listHl.push(product);
		}
		
		// update the summary list.
		this.updateSummary();
	}
	
	
	// ---- PController method: eventQtyChange
	PController.prototype.eventQtyChange = function( productId ) {
		var product = this.products[productId];
		if ( product == null )
			throw "'"+productId+"'is not a valid product.";
			
		product.eventQtyChange();
		this.updateSummary();
	}
	
	// ---- PController method: eventOptionChange
	PController.prototype.eventOptionChange = function( productId ) {
		//var product = this.products[productId];
		//if ( product == null )
		//	throw "'"+productId+"'is not a valid product.";
		this.updateSummary();
	}
	
	
	/************ End: class PController ************/


/* -------------------------------

	class Product( elContainerId, elQtyId, title, price, initialQuantity = 0 ) {
		// pass eId as null if unselectable
	
		var elContainer, elQty;
		var title, price;
		var quantity = initialQuantity;

		function do_highlight();
		function no_highlight();
		
		function changeQuantity();

	}
	
	class ProductsController(containerId) {
		var elSummary;
		var products[];
		
		function getElementById();
		function addProduct( product );
		
		function updateSummarY();
	}
	
	
	
	function products_select( id1,id2,id3, ... ) {
		// first unhighlight previously highlighted images,
		// clearing the list.
		
		// now, go through each idx
		//   get product by Id
		//   product.do_hl();  // highlight
		//   add to highlighted list
		//   product.force_qty(1) // set Qty to 1 (can be conditional == 0)
		//   add product to summary
		
		// update summary

	
// ------------------------------- */
