	var ORDER_ITEMS = new OrderItems();
	var BasketExtraUrlParams = new Array(); 
	function buyProduct(productId, quantity, forwardAction, purchaseLocation) 
	{
		ORDER_ITEMS.createItem(quantity, '0', productId, false, purchaseLocation);
		if( forwardAction != null && forwardAction.length > 0 ) {
			recalculateOrder(forwardAction);
		}
	}
	function buyPreOrderProduct(productId, quantity, forwardAction, purchaseLocation) 
	{
		alert("This title is due into the warehouse soon, but please be aware it may delay your order");
		buyProduct(productId, quantity, forwardAction, purchaseLocation);
	}
	function buyProducts(productSelectionList, forwardAction, purchaseLocation) {
		if( productSelectionList != null ) 
		{
			var numSelections = productSelectionList.length;
			if( numSelections != null )
			{
				for( var i=0 ; i < numSelections ; i++ ) {
					if( productSelectionList[i].checked ) {
						ORDER_ITEMS.createItem(1, '0', productSelectionList[i].value, false, purchaseLocation);
					}
				}
			}else{
				ORDER_ITEMS.createItem(1, '0', productSelectionList.value, false, purchaseLocation);
			}
		}
		if( forwardAction != null && forwardAction.length > 0 ) {
			recalculateOrder(forwardAction);
		}
	}
	function buyProductWithBookPoints(productId, quantity, forwardAction, purchaseLocation) {
		ORDER_ITEMS.createItem(quantity, '1', productId, false, purchaseLocation);
		addFormElement( createProductIdElement(productId) );
		if( forwardAction != null && forwardAction.length > 0 ) {
			recalculateOrder(forwardAction);
		}
	}
	function updateQuantity(orderItemId, quantity, forwardAction) 
	{
		var item = ORDER_ITEMS.getItemById(orderItemId);
		if( item != null ) 
		{
			item.setQuantity(quantity);
		}
		if( forwardAction != null && forwardAction.length > 0 ) 
		{
			recalculateOrder(forwardAction);
		}
	}
	function updatePreOrderQuantity(orderItemId, quantity, forwardAction) 
	{
		alert("This title is due into the warehouse soon, but please be aware it may delay your order");
		updateQuantity(orderItemId, quantity, forwardAction);
	}
	function deleteOrderItem(orderItemId, forwardAction) {
		var item = ORDER_ITEMS.getItemById(orderItemId);
		if( item != null ) {
			item.setDeleted(true);
		}
		if( forwardAction != null && forwardAction.length > 0 ) {
			recalculateOrder(forwardAction);
		}
	}
	function undeleteOrderItem(orderItemId) {
		var item = ORDER_ITEMS.getItemById(orderItemId);
		if( item != null ) {
			item.setDeleted(false);
		}
	}
	function addPromotionCode(promotionCode, forwardAction) {
		var frm = getShopCartForm();	
		frm.action = "PromotionCodeManage";
		handleFreeItems();
		addFormElement( createTaskTypeElement("A") );
		addFormElement( createPromotionCodeElement(promotionCode) );
		updateForm(forwardAction);
		if( !busy ) 
		{
			busy = true;
			frm.submit();
		}
	}
	function removePromotionCode(promotionCode, forwardAction) {
		var frm = getShopCartForm();
		frm.action="PromotionCodeManage";
		handleFreeItems();
		addFormElement( createTaskTypeElement("R") );
		addFormElement( createPromotionCodeElement(promotionCode) );

		updateForm(forwardAction);

		if( !busy ) {
			busy = true;
			frm.submit();
		}
	}
	function addProductToWishList(productId, forwardAction) {
		getShopCartForm().action="InterestItemAdd";
		addFormElement( createURLElement(forwardAction) );
		addFormElement( createAccountDisplayOptionElement("interestItem") );
		addFormElement( createWishListCatEntryElement(productId) );
		
		updateForm(forwardAction);

		if( !busy ) {
			busy = true;
			getShopCartForm().submit();
		}
	}
	// flag set to stop duplicate form submissions 
	var busy = false;
	var MAX_QUANTITY = 20;

	function recalculateOrder(forwardAction) {
		if( !busy ) {
			busy = true;
			if(ORDER_ITEMS.count() > 0) {
				getShopCartForm().action="OrderItemUpdate";
				handleFreeItems();
				updateForm(forwardAction);
			}
			getShopCartForm().submit();
		}
	}
	function OrderItem(id, quantity, redeem, productId, free, purchaseLocation) {
		this.id = id;
		this.quantity = quantity <= MAX_QUANTITY ? quantity : MAX_QUANTITY;
		this.redeem = redeem;
		this.productId = productId;
		this.free = free;
		this.deleted = false;
		this.field2 = purchaseLocation;
		this.getField2 = function getField2() {return this.field2;}
		this.setField2 = function setField2( field2 ) {this.field2 = field2;}
		this.isRedeemed = function isRedeemed() {return (this.redeem != null && this.redeem == '1');}
		this.isFree = function isFree() {return this.free != null && this.free;}
		this.getRedeemed = function getRedeemed() {return this.redeem;}
		this.getQuantity = function getQuantity() {
			if( this.deleted ) {return 0;}
			if( isNaN(this.quantity) ) {this.quantity = 1;}
			return this.quantity;
		}
		this.setQuantity = function(newQuantity) {
			if( newQuantity > MAX_QUANTITY ) {
				this.quantity = MAX_QUANTITY;
			}else{
				this.quantity = newQuantity;
			}
		}
		this.getId = function getId() {return this.id;}
		this.getProductId = function getProductId() {return this.productId;}
		this.setDeleted = function setDeleted(deleteFlag) {this.deleted = deleteFlag;}
		this.isDeleted = function isDeleted() {return this.deleted;}
	}
	function OrderItems() 
	{
		this.itemsByIndex = new Array();
		this.itemsById = new Array();
		this.addItem = function addItem(id, quantity, redeem, productId, isFree, purchaseLocation) {
			var newItem = new OrderItem(id, quantity, redeem, productId, isFree, purchaseLocation);
			
			this.itemsByIndex[this.itemsByIndex.length]= newItem;	
			this.itemsById[id] = newItem;
		}
		this.createItem = function createItem(quantity, redeem, productId, isFree, purchaseLocation) {
			var newItem = new OrderItem("-1", quantity, redeem, productId, isFree, purchaseLocation);
			this.itemsByIndex[this.itemsByIndex.length] = newItem;
		}
		this.getItemById = function getItemById(id) {return this.itemsById[id];}
		this.getItemByIndex = function getItemByIndex(index) {return this.itemsByIndex[index];}
		this.count = function count() {return this.itemsByIndex.length;}
		this.getRedeemedItems = function getRedeemedItems() {
			var redeemedItems = new Array();
			var numItems = this.count();
			
			for(var i=0 ; i < numItems ; i++) {
				if( this.itemsByIndex[i].isRedeemed() ) {
					// redeemedItems.push(this.itemsByIndex[i]);
					redeemedItems[redeemedItems.length] =  this.itemsByIndex[i];
				}
			}
			return redeemedItems;
		}
		this.getUnredeemedItems = function getUnredeemedItems() {
			var unredeemedItems = new Array();
			var numItems = this.count();
			
			for(var i=0 ; i < numItems ; i++) {
				if( !this.itemsByIndex[i].isRedeemed() ) {
					unredeemedItems[unredeemedItems.length] = this.itemsByIndex[i];
				}
			}
			return unredeemedItems;
		}
		this.getFreeItems = function getFreeItems() {
			var freeItems = new Array();
			var numItems = this.count();
			
			for(var i=0 ; i < numItems ; i++) 
			{
				if( this.itemsByIndex[i].isFree() && !this.itemsByIndex[i].isRedeemed() ) 
				{
					freeItems[freeItems.length] = this.itemsByIndex[i];
				}
			}
			return freeItems;
		}
		this.getItemByProductId = function getItemByProductId(productId) {
			var numItems = this.count();
			var foundItem = null;
			if( productId != null && productId.length > 0 ) {
				for(var i=0 ; i < numItems ; i++) {
					var currentItem = this.itemsByIndex[i];
					if( currentItem.getProductId() == productId && !currentItem.isFree() ) {
						foundItem = currentItem;
					}
				}
			}
			return foundItem;
		}
		this.getMatchingItem = function getMatchingItem(itemToMatch) {
			var matchItems = null;
			var matchedItem = null;
			
			if( itemToMatch.isRedeemed() )
				matchItems = this.getUnredeemedItems();
			else {
				matchItems = this.getRedeemedItems();
			}
			var numItems = matchItems.length;
			
			for(var i=0 ; i < numItems ; i++) {
				if( (matchItems[i].getProductId() == itemToMatch.getProductId()) &&
					!matchItems[i].isFree() ) {
					matchedItem = matchItems[i];
					break;
				}
			}
			return matchedItem;
		}
	}
	function getOrderCalculateAction(forwardAction) {
		return BASE_CALCULATE_URL + getExtraUrlParamString() + "&URL=" + forwardAction;
	}	
	function getExtraUrlParamString() {
		var extraParams = "";
		var numParams = BasketExtraUrlParams.length;
		if( numParams > 0 ) {
			extraParams += "&";
			for(var i=0 ; i < numParams ; i++ ) {
				extraParams += BasketExtraUrlParams[i];
				if( (i + 1) < numParams ) {
					extraParams += "&";
				}
			}
		}
		return extraParams;
	}
	function getShopCartForm() {
		return document.ShopCartForm; 
	}
	function updateForm(forwardAction) {
		var numUpdates = ORDER_ITEMS.count();
		for( var i = 0 ; i < numUpdates ; i++ ) {
			addFormElement( createOrderItemElement(i) );
			addFormElement( createQuantityElement(i) );
			addFormElement( createRedeemElement(i) );
			addFormElement( createCatEntryElement(i) );
			addFormElement( createPurchaseLocationElement(i) );
		}
		addFormElement( createURLElement(forwardAction) );
	}
	function handleFreeItems() 
	{
		var freeItems = ORDER_ITEMS.getFreeItems();
		for(var i=0 ;  i < freeItems.length ; i++) 
		{
			if( !freeItems[i].isRedeemed() ) {
				freeItems[i].setDeleted(true);
			}
		}
	}
	function addFormElement(element) {
		if( element != null ) {
			getShopCartForm().appendChild( element );
		}
	}
	function createOrderItemElement(index) {
		var inputElement = null;
		var orderItemId = ORDER_ITEMS.getItemByIndex(index).getId();
		if( orderItemId != "-1" ) {
			inputElement = document.createElement("input");
			inputElement.type = "HIDDEN";
			inputElement.name = "orderItemId_" + (index+1);
			inputElement.value = orderItemId;
		}
		return inputElement;
	}
	function createQuantityElement(index) {
		var inputElement = document.createElement("input");
		inputElement.type = "HIDDEN";
		inputElement.name = "quantity_" + (index+1);
		inputElement.value = ORDER_ITEMS.getItemByIndex(index).getQuantity();
		return inputElement;
	}
	function createRedeemElement(index) {
		var inputElement = document.createElement("input");
		inputElement.type = "HIDDEN";
		inputElement.name = "field1_" + (index+1);
		inputElement.value = ORDER_ITEMS.getItemByIndex(index).getRedeemed();
		return inputElement;
	}
	function createCatEntryElement(index) {
		var inputElement = document.createElement("input");
		inputElement.type = "HIDDEN";
		inputElement.name = "catEntryId_" + (index+1);
		inputElement.value = ORDER_ITEMS.getItemByIndex(index).getProductId();
		return inputElement;
	}
	function createWishListCatEntryElement(index) {
		var inputElement = document.createElement("input");
		inputElement.type = "HIDDEN";
		inputElement.name = "catEntryId";
		inputElement.value = index;
		return inputElement;
	}
	function createURLElement(forwardAction) {
		var inputElement = null;
		if( forwardAction != null && forwardAction.length > 0 ) {
			inputElement = document.createElement("input");
			inputElement.type = "HIDDEN";
			inputElement.name = "URL";
			inputElement.value = getOrderCalculateAction(forwardAction);
		}
		return inputElement;
	}
	function createTaskTypeElement(taskCode) {
		var inputElement = document.createElement("input");
		inputElement.type = "HIDDEN";
		inputElement.name = "taskType";
		inputElement.value = taskCode;
		return inputElement;
	}
	function createPromotionCodeElement(promotionCode) {
		var inputElement = document.createElement("input");
		inputElement.type = "HIDDEN";
		inputElement.name = "promoCode";
		inputElement.value = promotionCode.toUpperCase();
		return inputElement;
	}
	function createProductIdElement(productId) {
		var inputElement = document.createElement("input");
		inputElement.type = "HIDDEN";
		inputElement.name = "productId";
		inputElement.value = productId;
		return inputElement;
	}
	function createPurchaseLocationElement(index) 
	{
		var inputElement = document.createElement("input");
		inputElement.type = "HIDDEN";
		inputElement.name = "field2_" + (index +1);
		inputElement.value = ORDER_ITEMS.getItemByIndex(index).getField2();
		return inputElement;
	}
	function createAccountDisplayOptionElement(value)
	{
		var inputElement   = document.createElement("input");
		inputElement.type  = "HIDDEN";
		inputElement.name  = "accountDisplayOption";
		inputElement.value = value; 
		
		return inputElement;
	}