///////////////////////////////////////////////////////////////////////
// Amazon Command Line Interface Javascript -
//  
// An experiment in UI
// An experiment in AWS
// An experiment in AJAX
// 
// This script acts as the engine for the CLI. 
// Core functionality includes dynamically parsing the command line, 
// triggering appropriate actions based on user events, 
// dispatching asynchoronous XmlHttpRequests to the server side
// proxy for AWS Operations, and transforming the response XML
// to displayable HTML. 
// 
// Author: Ammar Chinoy
// Email: achinoy@amazon.com
//
// External AJAX Libraries used:
// Prototype - for primitive DOM handling
// Scriptaculous - for basic GUI effects
// AJAXSLT - Parsing XML responses
/////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////
//// AMAZON CLI GLOBAL VARIABLE AND CLASS DECLARATIONS
////////////////////////////////////////////////////////
var AWSProxyUrl = '../../cgi-bin/acTerm.cgi';
var godMode = 0;
var autoCompletion = 0;
var globalAppendCount = 1;
var uniqueDivId = 1;
var globalArrayOfASINs = new Array();
var ASINdex = 1;
var autoCompletionKeywords = new Array('search','cart','lookup','checkout','-id','-i','-index','-k','-keywords','-p','-page', 
													'--append','-add', '-clear','debug','style', 'clear','--help', 'whoami', 'about',
													'help','-create','-view','-purchase','-q','-Quantity','-ItemId', '-type','-IdType', '-SearchIndex',
													'-Artist', '-Actor', '-Author','-Title','-s', '-Sort', '-r', 'Director', 'AudienceRating',
													'Manufacturer', 'MusicLabel', 'Composer', 'Publisher', 'Brand', 'Conductor', 'Orchestra', 
													'TextStream', 'City', 'Cuisine', 'Neighborhood', 'MinimumPrice', 'MaximumPrice', 'MerchantId', 'Condition', 'DeliveryMethod', 
													'Apparel', 'Automotive',
													'Baby','Beauty','Blended','Books','Classical','DigitalMusic','DVD','Electronics',
													'GourmetFood','HealthPersonalCare','Jewelry','Kitchen','Magazines','Merchants',
													'Miscellaneous','MP3Downloads','Music','MusicalInstruments','MusicTracks','OfficeProducts','OutdoorLiving',
													'PCHardware','PetSupplies','Photo','Restaurants','Software','SportingGoods','Tools','Toys',
													'VHS','Video','VideoGames','Wireless','WirelessAccessories');

///// SHOPPING CART
var shoppingCart = Class.create();
shoppingCart.prototype = {
	    initialize: function(){
		 this.CartId = '0';
		 this.HMAC = '0';
		 this.numItems = 0;
		 this.cartOneLiner = '';
	    },
	    createDefaultCart: function (){
		 			var pars = 'Operation=CartCreate&Item.1.ASIN=0439784549&Item.1.Quantity=1&ResponseGroup=Cart'; 
	        		var operationRequest = new Ajax.Request( AWSProxyUrl, {method: 'post', parameters: pars, onComplete: shoppingCart.prototype.createDefaultCartCallback} ); 
	    },
	    createDefaultCartCallback: function ( originalRequest ){
   	         var myXML = new ExprContext(originalRequest.responseXML);
               var cid = xpathParse("/CartCreateResponse/Cart/CartId/text()").evaluate(myXML).nodeSetValue();
		 			var uhmac = xpathParse("//Cart/URLEncodedHMAC/text()").evaluate(myXML).nodeSetValue();
		 			CartId = cid[0].nodeValue;
		 			HMAC = uhmac[0].nodeValue;
  		 			shoppingCart.prototype.clearCart();
	    },
	    addToCart: function ( ItemId , ItemQuantity ){
	        		if( CartId == '0' || HMAC == '0'  ){
	          			cartOneLiner = "Can't add items, you need to create a cart first. Try 'cart -help' for more info";
		  					shoppingCart.prototype.displayCartOneLiner();
					}
					else{
		  					var pars = 'Operation=CartAdd';
		  					pars += '&CartId=' + CartId;
		  					pars += '&HMAC=' + HMAC;
		  					pars += '&Item.1.ASIN=' + ItemId;
		  					pars += '&Item.1.Quantity=' + ItemQuantity;
  	          			var operationRequest = new Ajax.Request( AWSProxyUrl, {method: 'post', parameters: pars, onComplete: shoppingCart.prototype.addToCartCallback} ); 		
					}
	    },
	    addToCartCallback: function ( originalRequest ){
	    	  var myXML = new ExprContext( originalRequest.responseXML );
	        var isVal = xpathParse("/CartAddResponse/Cart/Request/IsValid/text()").evaluate(myXML).nodeSetValue();
	        if( isVal[0].nodeValue != "True"){
   	    	   cartOneLiner = 'Failed to add item to shopping cart';
	        } 
	        else{
		    cartOneLiner = 'Added item to shopping cart';
	        }
	        shoppingCart.prototype.displayCartOneLiner();
	    },
	    getCart: function () {
	        if( CartId == '0' || HMAC =='0' ){
	           cartOneLiner = "Can't add items, you need to create a cart first. Try 'cart -help' for more info";
		   	  shoppingCart.prototype.displayCartOneLiner();
	        }
			  else{
		       var pars = 'Operation=CartGet';
		       pars += '&CartId=' + CartId;
		  		 pars += '&HMAC=' + HMAC;
  	          var operationRequest = new Ajax.Request( AWSProxyUrl, {method: 'post', parameters: pars, onComplete: shoppingCart.prototype.getCartCallback} ); 		
                  //var request = 'http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&Version=2005-03-23&SubscriptionId=10GJZ2S7EVK4A1DGW6R2&' + pars + '&ResponseGroup=Cart';
	          //defaultResponse( request );
	        }
	    },
	    getCartCallback: function ( originalRequest ){
	        var myXML = new ExprContext( originalRequest.responseXML );
		     var cartItemsTitle = xpathParse("/CartGetResponse/Cart/CartItems/CartItem/Title/text()").evaluate(myXML).nodeSetValue();
			  var cartItemsQuantity = xpathParse("/CartGetResponse/Cart/CartItems/CartItem/Quantity/text()").evaluate(myXML).nodeSetValue();
			  var cartItemsProductGroup = xpathParse("/CartGetResponse/Cart/CartItems/CartItem/ProductGroup/text()").evaluate(myXML).nodeSetValue();
			  var cartItemsPrice = xpathParse("/CartGetResponse/Cart/CartItems/CartItem/Price/FormattedPrice/text()").evaluate(myXML).nodeSetValue();
			  var cartItemsTotalPrice = xpathParse("/CartGetResponse/Cart/CartItems/CartItem/ItemTotal/FormattedPrice/text()").evaluate(myXML).nodeSetValue();
			  var cartSubTotal = xpathParse("/CartGetResponse/Cart/SubTotal/FormattedPrice/text()").evaluate(myXML).nodeSetValue();
			  var nodeSetSize = cartItemsTitle.length;
		
   		////// CONSTRUCT THE TABLE OBJECT
		   var curr = 0;
   		var oTable = document.createElement("TABLE");
   		oTable.border = 0;
   		oTable.setAttribute('width', '95%');
   		oTable.id = "cartRes";
   		var oTableBody = document.createElement("TBODY");

      ////// TABLE HEADER INFORMATION
   	var itemsPerRow = 4; 
   	var cell_width = 95 / itemsPerRow;
   	cell_width += '%';
		
   	oTableHeadRow = document.createElement("TR");
		
		oTableHeadItem = document.createElement("TD");
		oTableHeadItem.setAttribute('width', cell_width );
		oTableHeadItem.appendChild( document.createTextNode( " ITEM " ) );
		oTableHeadItem.setAttribute('class', 'mediumText' );
		oTableHeadRow.appendChild( oTableHeadItem );
		
		oTableHeadItem = document.createElement("TD");
		oTableHeadItem.setAttribute('width', cell_width );
		oTableHeadItem.appendChild( document.createTextNode( " QUANTITY " ) );
		oTableHeadItem.setAttribute('class', 'mediumText' );
		oTableHeadRow.appendChild( oTableHeadItem );
		
		oTableHeadItem = document.createElement("TD");
		oTableHeadItem.setAttribute('width', cell_width );
		oTableHeadItem.appendChild( document.createTextNode( " PRICE " ) );
		oTableHeadItem.setAttribute('class', 'mediumText' );
		oTableHeadRow.appendChild( oTableHeadItem );
		
		oTableHeadItem = document.createElement("TD");
		oTableHeadItem.setAttribute('width', cell_width );
		oTableHeadItem.appendChild( document.createTextNode( " ITEM TOTAL " ) );
		oTableHeadItem.setAttribute('class', 'mediumText' );
		oTableHeadRow.appendChild( oTableHeadItem );
		
		oTableBody.appendChild( oTableHeadRow );
		oTableBody.appendChild( document.createElement("TR").appendChild( document.createElement("BR") ) );

	        ///// DISPLAY INFORMATION ABOUT EACH ITEM IN THE CART (ITEM, PRICE, QUANTITY, TOTALS )
		for(var i = 0; i < nodeSetSize; i++){
		
		    oTableItemRow = document.createElement("TR");
		   
		    oTableItemInfo = document.createElement("TD");
		    oTableItemInfo.setAttribute('width', cell_width );
		    oTableItemInfo.appendChild( document.createTextNode( cartItemsTitle[i].nodeValue + " (" + cartItemsProductGroup[i].nodeValue + ") " ) );
		    oTableItemRow.appendChild( oTableItemInfo );
		  
		    oTableItemInfo = document.createElement("TD");
		    oTableItemInfo.setAttribute('width', cell_width );
		    oTableItemInfo.appendChild( document.createTextNode( cartItemsQuantity[i].nodeValue ) );
		    oTableItemRow.appendChild( oTableItemInfo );

		    oTableItemInfo = document.createElement("TD");
		    oTableItemInfo.setAttribute('width', cell_width );
		    oTableItemInfo.appendChild( document.createTextNode( cartItemsPrice[i].nodeValue ) );
		    oTableItemRow.appendChild( oTableItemInfo );
		  
		    oTableItemInfo = document.createElement("TD");
		    oTableItemInfo.setAttribute('width', cell_width );
		    oTableItemInfo.appendChild( document.createTextNode( cartItemsTotalPrice[i].nodeValue ) );
		    oTableItemRow.appendChild( oTableItemInfo );
		    
		    oTableBody.appendChild( oTableItemRow );
		    oTableBody.appendChild( document.createElement("TR").appendChild( document.createElement("BR") ) );
		}
		
		////// DISPLAY CART SUB TOTAL
		oTableCartSubTotal = document.createElement("TR")
	   oTableCartSubTotal.appendChild( document.createTextNode( "Cart Total: " + cartSubTotal[0].nodeValue ) );
		oTableCartSubTotal.setAttribute('class', 'mediumText');
		oTableBody.appendChild( oTableCartSubTotal );
		
		oTable.appendChild( oTableBody );
		$('cliResult').innerHTML = '';
   	$('cliResult').appendChild( oTable );

		Effect.SlideUp('lo');
		Effect.SlideDown('cliResult');
	   },
	    clearCart: function () { 
		 		var pars = 'Operation=CartClear&ResponseGroup=Cart';
		 		pars += '&CartId=' + CartId;
		 		pars += '&HMAC=' + HMAC;
  	         var operationRequest = new Ajax.Request( AWSProxyUrl, {method: 'post', parameters: pars, onComplete: shoppingCart.prototype.clearCartCallback} ); 		
	    },
	    clearCartCallback: function ( originalRequest ){
            var myXML = new ExprContext( originalRequest.responseXML );
				var isVal = xpathParse("/CartClearResponse/Cart/Request/IsValid/text()").evaluate(myXML).nodeSetValue();
				if( isVal[0].nodeValue != "True"){
   	    		cartOneLiner = 'Failed to clear shopping cart';
				}
				else{
		  			cartOneLiner = 'Shopping cart ' + CartId + ' is now empty.';
				}
				shoppingCart.prototype.displayCartOneLiner();
	    },
	    purchaseCart: function () {
		 	var pars = 'Operation=CartGet';
			pars += '&CartId=' + CartId;
			pars += '&HMAC=' + HMAC;
  	      var operationRequest = new Ajax.Request( AWSProxyUrl, {method: 'post', parameters: pars, onComplete: shoppingCart.prototype.purchaseCartCallback} ); 		
	    },
	    purchaseCartCallback: function ( originalRequest ) {
	      var myXML = new ExprContext( originalRequest.responseXML );
         var purchaseUrl = xpathParse("/CartGetResponse/Cart/PurchaseURL/text()").evaluate(myXML).nodeSetValue();
		 	if( !purchaseUrl[0] ){
		   	cartOneLiner = 'Your shopping cart is empty - unable to proceed to checkout';
		   	shoppingCart.prototype.displayCartOneLiner();
		   }
			else{
		   	defaultResponse( purchaseUrl[0].nodeValue );
			}
	    },
	    displayCartOneLiner: function (){
	    	Effect.SlideUp('lo');
		 	$('cartOneLiner').innerHTML = cartOneLiner;
	      Effect.Appear("cartOneLiner");
		 	setTimeout("Effect.Fade('cartOneLiner')", 2000);
	    },
	    getCartId: function (){
		 	return CartId;
	    },
	    getHMAC: function (){
	    	return HMAC;
	    },
	    getNumItems: function (){
 		 	return numItems;
	    }
};

///// REGISTER GLOBAL AJAX HANDLERS
var globalAjaxHandlers = {
	    onFailure: function() {
		window.alert("Somebody or something, somewhere, fucked up. Retry the operation or reload the app");
	    }
};
Ajax.Responders.register(globalAjaxHandlers);



	    

//////////////////////////////////////////////////////////
// Intialization Function
// Grab global boxes, creates images, browser detect etc.
//////////////////////////////////////////////////////////
function init () {
  //Grab the user input box, and appended content box
  userbox = document.getElementById ? document.getElementById('cli') : document.all['cli'];
  contentbox = document.getElementById ? document.getElementById('contentcell') : document.all['contentcell'];

  //Apply Auto-completion to user input box
  var obj = actb(document.getElementById('cli'), autoCompletionKeywords);

  //Pre-load images here
  img_on  = new Image();  img_on.src ="IMAGES/minus1.jpg"; 
  img_off = new Image();  img_off.src="IMAGES/minus2.jpg";
  redStar100 = new Image(); redStar100.src = "IMAGES/STARS/star100.gif";
  redStar50 = new Image(); redStar50.src = "IMAGES/STARS/star50.gif";
  redStar0 = new Image(); redStar0.src = "IMAGES/STARS/star0.gif";
  notAvail = new Image(); notAvail.src = "IMAGES/notavail.jpg";

  //If Browser is IE, tell user to get Firefox 
  var browserDetect = navigator.userAgent.toLowerCase();
  if( (browserDetect.indexOf('msie') + 1) ){
    window.alert("Internet Explorer is NOT supported. Download Firefox for a better life." );
  }
  shoppingCart.prototype.initialize(); 
  shoppingCart.prototype.createDefaultCart();
  userbox.focus();
}


//////////////////////////////////////////////
// Function to dynamically switch stylesheets
//////////////////////////////////////////////
function initStyle( styleId ) {
  var styleTitle = 'AltStyle' + styleId;
  if( styleId == '0' || !styleId ){
      setActiveStyleSheet('DefaultStyle');
  }
  else{
      setActiveStyleSheet(styleTitle);
  }
}


///////////////////////////////////////////////////////////
// The main function - triggered on a user based
// keyboard event, and invokes functions accordingly.
///////////////////////////////////////////////////////////
function doframe(event){

  var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;

  ///// UP ARROW - GET PREVIOUS COMMAND FROM INPUT HISTORY
  if ( keyCode == 33 /*38*/ ){
     userbox.value = getPreviousCmd();
     return false;     
  }
 
  ///// DOWN ARROW - GET NEXT COMMAND FROM INPUT HISTORY
  else if ( keyCode == 34 /*40*/ ){
     userbox.value = getNextCmd();
     return false;
  }

  //// ENTER KEY PRESS - SUBMIT COMMAND
  if (keyCode == 13 && userbox.value > " ") {
	
	//// ADD TO COMMAND LINE HISTORY, AND CHECK FOR SIMPLE COMMANDS FIRST
   enqueue( userbox.value );
	var clicmd = userbox.value;
	var clicmd = convertWhiteSpace( clicmd );

	var args = [];
	args = clicmd.split(' ');

	if( clicmd == "?" || clicmd == "help" || clicmd == "man" ){
	  Effect.SlideDown("help"); reInit(); return;
	}

	if( clicmd == "bugs"){
	  Effect.SlideDown("bugs"); reInit(); return; 
	}

	if( clicmd=="clear" || clicmd=="Clear" || clicmd=="cls"){
	   $('bugs').setAttribute('style', 'display:none');
	   $('help').setAttribute('style', 'display:none');
	   $('bizcard').setAttribute('style', 'display:none');
	   uniqueDivId++;
	   new Effect.Fade("cliResult"); reInit(); return;
	}

	if( clicmd=="fadeOut" || clicmd=="fadeout"){
           new Effect.Opacity('cliResult', { duration: 2.0, transition: Effect.Transitions.linear, from: 1.0, to: 0.2 });   reInit();  return;
	}

	if( clicmd=="fadeIn" || clicmd == "fadein"){
	   new Effect.Opacity('cliResult', { duration: 2.0, transition: Effect.Transitions.linear, from: 0.2, to: 1.0});    reInit();  return;
	}

	if( (args[0] == "fade" || args[0] == "Fade") && args[1] >= 0.1 && args[1] <= 1 && args.length == 2 ){
	   new Effect.Opacity('cliResult', { duration: 2.0, transition: Effect.Transitions.linear, from: 1.0, to: args[1]});    reInit();  return;
	}
	
	if( (args[0] == "style" || args[0] == "Style") && (args[1] == "-id") && (args[2] >= 0 && args[2] <= 3) && args.length == 3 ){
	   initStyle( args[2] );  reInit();  return;
	}

	if( clicmd == "whoami" || clicmd == "info" ){
	    Effect.SlideDown("bizcard"); reInit(); return;
	}

	//if( clicmd == "auto" || clicmd == "Auto"){
	//  autoCompletion = autoCompletion ? 0 : 1;
   //    var obj = actb(document.getElementById('cli'), autoCompletionKeywords);
	//  reInit(); return;
   //	}

	if( clicmd == "about" ){
	   $('cliResult').innerHTML = clearButtonHTML();
           var helpUrl = 'DOCS/WhyACLIHelp';
           var helpPars = '';
           var helpRequest = new Ajax.Request( helpUrl, {method: 'get', parameters: helpPars, onComplete: displayHelp} );
	   reInit(); return;
	}

	if( clicmd == "history" || clicmd == "History" ){
		var history = getQueue();
		$("cliResult").innerHTML = '';
		for(n = 0; n < history.length; n++){
			$("cliResult").appendChild( document.createTextNode( history[n] ) );
			$("cliResult").appendChild( document.createElement("BR") );
		}
		Effect.SlideDown("cliResult");
	}

	if( clicmd == "checkout" ){
	   shoppingCart.prototype.purchaseCart();
	   reInit(); return;
	}
	
	if( clicmd == "god" || clicmd == "God" || clicmd == "Debug" || clicmd == "debug" ){
	  godMode = godMode ? 0 : 1;
	  if( godMode ){
   	     Effect.Appear("godOn");
	     setTimeout("Effect.Fade('godOn')", 1700);
	  }
	  else{
	     Effect.Appear("godOff");
	     setTimeout("Effect.Fade('godOff')", 1700);
	  }
	  reInit(); return;
	}

   /////// PARSE THE COMMAND LINE, POPULATE HASH WITH ARGUMENTS TBUL, AND VALIDATE THE OPERATION 
   var cmdHash = parseCommandLine( args ); 
	var operationInfo = validateOperation( cmdHash );
 
   ////// AWS ECS REQUEST - ISSUE APPROPRIATE AJAX REQUEST TO FETCH XML
	if( operationInfo['IsValid'] == 'Yes' && operationInfo['Help'] != 'Yes'){
         
	   //// CHECK TO SEE IF WE WANT TO APPEND RESULTS OR START AFRESH
	   if( !operationInfo['Append'] ){
	      $('cliResult').innerHTML = '';
	      globalAppendCount = 1;
	      ASINdex = 1;
      }
	  
      Effect.SlideDown('lo');
	   var pars = 'Operation=' +  operationInfo['Operation'];
	   pars += operationInfo['OtherParams'];

      /////// GOD MODE - DISPLAY XML AS IS IN BROWSER
	   if( godMode ){
			var isCartOp = /^Cart/;
			if( operationInfo['Operation'].match(isCartOp) ){
				pars += '&AssociateTag=amazoncli-20';
				pars += '&CartId=' + shoppingCart.prototype.getCartId();
				pars += '&HMAC=' + shoppingCart.prototype.getHMAC();
			}
         var request = 'http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&Version=2005-03-23&SubscriptionId=10GJZ2S7EVK4A1DGW6R2&' + pars;
	      defaultResponse( request ); reInit(); 
	      return;
	   }
	   
	   /////// MAKE ITEMSEARCH CALL
	   if( operationInfo['Operation'] == "ItemSearch" ){
	     var operationRequest = new Ajax.Request( AWSProxyUrl, {method: 'post', parameters: pars, onComplete: itemSearchResponse} ); reInit();
	     return;
	   }
	   ////// MAKE ITEMLOOKUP CALL 
	   else if( operationInfo['Operation'] == "ItemLookup" ){
	     var operationRequest = new Ajax.Request( AWSProxyUrl, {method: 'post', parameters: pars, onComplete: itemLookupResponse} ); reInit();
	     return;
	   }   
	   ////// MAKE APPROPRIATE CART CALL
	   else if( operationInfo['Operation'] == "CartCreate" ){
	     shoppingCart.prototype.createDefaultCart();
	     reInit(); return;
	   }
	   else if( operationInfo['Operation'] == "CartAdd" ){
        shoppingCart.prototype.addToCart( operationInfo['Item.1.ASIN'] , operationInfo['Item.1.Quantity'] );
	     reInit(); return;
	   }
	   else if( operationInfo['Operation'] == "CartGet" ){
	     shoppingCart.prototype.getCart();
	     reInit(); return;
	   }
	   else if( operationInfo['Operation'] == "CartPurchase" ){
	     shoppingCart.prototype.purchaseCart();
	     reInit(); return;
	   }
	}
	/////// CALL THE HELP FUNCTION TO DISPLAY THE HELP FOR SPECIFIED OPERATION
	else if( operationInfo['Help'] == 'Yes'){
	   Help( operationInfo );
	}
	/////// COMMAND NOT RECOGNIZED - DISPLAY ERROR MESSAGE
	else{
		Effect.Appear("badcommand");
	   setTimeout("Effect.Fade('badcommand')",3500);
	}
	reInit();
  }
}


//////////////////////////////////////////////////////////
// This function is called at the end of the AJAX
// ItemLookup request, to parse XML and convert to 
// a detail page for a specific item.
//////////////////////////////////////////////////////////
function itemLookupResponse(originalRequest){

   ///// DISABLE XPATH & XSLT DEBUG DIALOG BOX
   xpathdebug = false;
   xsltdebug = false;

   var myXML = new ExprContext(originalRequest.responseXML);

   ///// PARSE OUT ALL THE ARGUMENTS THAT ARE ECHOED BACK IN THE REQUEST
   var arguments = xpathParse("//OperationRequest/Arguments/Argument").evaluate(myXML);
   var argumentHash = new Object;
   for( a = 0; a < arguments.value.length; a++ ){
      argumentName =  xpathParse('@Name').evaluate(new ExprContext(arguments.value[a])).stringValue(); 
      argumentValue = xpathParse('@Value').evaluate(new ExprContext(arguments.value[a])).stringValue();
      argumentHash[argumentName] = argumentValue;
   }

   /////// CHECK TO SEE IF THE RESPONSE IS VALID, AND DISPLAY APPROPRIATE ERROR MESSAGE(S)
   var isValid = xpathParse("/ItemLookupResponse/Items/Request/IsValid/text()").evaluate(myXML).nodeSetValue();
   var errorMsgs =  xpathParse("/ItemLookupResponse/Items/Request/Errors/Error/Message/text()").evaluate(myXML).nodeSetValue();
   if( (isValid[0].nodeValue == "False") || errorMsgs[0] ){
      for( var x = 0; x < errorMsgs.length; x++ ){
         var errDiv = document.createElement("DIV");
         var err = document.createTextNode('ERROR: ' + errorMsgs[x].nodeValue );
	      errDiv.setAttribute('class', 'errorText');
	      errDiv.appendChild(err);
      }
      errDiv.appendChild( document.createElement("BR") );
      errDiv.appendChild( document.createElement("BR") );
      errDiv.appendChild( document.createTextNode("Type 'lookup -help' for more information") );
      $('cliResult').appendChild( errDiv );
      Effect.SlideUp('lo');
      Effect.SlideDown('cliResult');
      return false;
   }

   /////// PARSE THE RESULTING XML FOR RELEVANT INFORMATION AND STORE IN LOCAL ARRAYS
   var title = xpathParse("/ItemLookupResponse/Items/Item/ItemAttributes/Title/text()").evaluate(myXML).nodeSetValue();
   var price = xpathParse("/ItemLookupResponse/Items/Item/ItemAttributes/ListPrice/FormattedPrice/text()").evaluate(myXML).nodeSetValue();
   var productGroup = xpathParse("/ItemLookupResponse/Items/Item/ItemAttributes/ProductGroup/text()").evaluate(myXML).nodeSetValue();
   var salesRank = xpathParse("/ItemLookupResponse/Items/Item/SalesRank/text()").evaluate(myXML).nodeSetValue();
   var largeImages =  xpathParse("/ItemLookupResponse/Items/Item/LargeImage/URL/text()").evaluate(myXML).nodeSetValue();
   var detailPageUrl =  xpathParse("/ItemLookupResponse/Items/Item/DetailPageURL/text()").evaluate(myXML).nodeSetValue();
   var asin =  xpathParse("/ItemLookupResponse/Items/Item/ASIN/text()").evaluate(myXML).nodeSetValue();
   var reviewAvgRating = xpathParse("/ItemLookupResponse/Items/Item/CustomerReviews/AverageRating/text()").evaluate(myXML).nodeSetValue();
   var reviewTotal = xpathParse("/ItemLookupResponse/Items/Item/CustomerReviews/TotalReviews/text()").evaluate(myXML).nodeSetValue();
   var reviewRating = xpathParse("/ItemLookupResponse/Items/Item/CustomerReviews/Review/Rating/text()").evaluate(myXML).nodeSetValue();
   var reviewSummary = xpathParse("/ItemLookupResponse/Items/Item/CustomerReviews/Review/Summary/text()").evaluate(myXML).nodeSetValue();
   var reviewContent = xpathParse("/ItemLookupResponse/Items/Item/CustomerReviews/Review/Content/text()").evaluate(myXML).nodeSetValue();
   var edReviewSource = xpathParse("/ItemLookupResponse/Items/Item/EditorialReviews/EditorialReview/Source/text()").evaluate(myXML).nodeSetValue();
   var edReviewContent = xpathParse("/ItemLookupResponse/Items/Item/EditorialReviews/EditorialReview/Content/text()").evaluate(myXML).nodeSetValue();
   var simProductAsin = xpathParse("/ItemLookupResponse/Items/Item/SimilarProducts/SimilarProduct/ASIN/text()").evaluate(myXML).nodeSetValue();
   var simProductTitle = xpathParse("/ItemLookupResponse/Items/Item/SimilarProducts/SimilarProduct/Title/text()").evaluate(myXML).nodeSetValue();

   var author = xpathParse("/ItemLookupResponse/Items/Item/ItemAttributes/Author/text()").evaluate(myXML).nodeSetValue();
   var artist = xpathParse("/ItemLookupResponse/Items/Item/ItemAttributes/Artist/text()").evaluate(myXML).nodeSetValue();
   var numDiscs = xpathParse("/ItemLookupResponse/Items/Item/Tracks/Disc").evaluate(myXML);
   
  
   /////// CREATE THE BASIC DISPLAY TABLE
   var curr = 0;
   var oTable = document.createElement("TABLE");
   oTable.setAttribute('border', '0');
   var oTableBody = document.createElement("TBODY");
   oTableHeadRow = document.createElement("TR");
   oTableLeftCell = document.createElement("TD");
   oTableLeftCell.setAttribute('width', '30%');
   oTableLeftCell.setAttribute('valign', 'top');
   oTableRightCell = document.createElement("TD");
   oTableRightCell.setAttribute('width', '70%');
   
   ////// DISPLAY PRODUCT IMAGE AND LINK TO AMAZON.COM DETAIL PAGE
   if( detailPageUrl[curr] ) {
	       var imageDiv = document.createElement("DIV");
	       var imgId = "image" + curr;
	       imageDiv.setAttribute('id', imgId);
	       imageDiv.setAttribute('align', 'center');
	       
	       var currImg = new Image();
	       if( largeImages[curr]){
	           currImg.src = largeImages[curr].nodeValue;
	       }
	       else{
	           currImg.src = notAvail.src;
	       }

	       var currLink = document.createElement("A");
	       currLink.setAttribute("href", "#");
	       currLink.setAttribute('onclick', "userbox.value\=\'cart -add -id " + asin[curr].nodeValue + "\'\; userbox.focus\(\)\; return false\;");
	        
	       newImage = document.createElement("IMG");
	       newImage.setAttribute('src', currImg.src );
	       newImage.setAttribute('height', '75%' );
	       newImage.setAttribute('width', '75%' );
	       
	       currLink.appendChild( newImage );
	       imageDiv.appendChild( currLink );
	       imageDiv.appendChild( document.createElement("BR") );
	       imageDiv.appendChild( document.createElement("BR") );
	    
	       var detailPageLink = document.createElement("A");
	       var detailPager = detailPageUrl[curr].nodeValue;
	       detailPageLink.setAttribute("href", "#" );
	       detailPageLink.setAttribute("onclick", "defaultResponse\(\'" + detailPager + "\'\)\;");  
	       var detailPageLinkTitle = document.createTextNode("Go to Amazon.com Detail Page");
	       detailPageLink.appendChild( detailPageLinkTitle );

	       imageDiv.appendChild( detailPageLink );
	       oTableLeftCell.appendChild( imageDiv );
   }
   
   ////// DISPLAY PRODUCT TITLE AND OTHER RELEVANT INFO
   var titleDiv = document.createElement("DIV");
   titleDiv.setAttribute('class', 'bigText');
   var titleNode = document.createTextNode(  title[curr].nodeValue );
   titleDiv.appendChild( titleNode );
   oTableRightCell.appendChild( titleDiv );

   var cat = productGroup[curr].nodeValue;

   if( author[curr] && cat == 'Book' ) { oTableRightCell.appendChild( document.createTextNode( 'written by ' + author[curr].nodeValue ) ); }
   if( author[curr] && cat == 'Book' ) { oTableRightCell.appendChild( document.createElement("BR") ); }
   if( author[curr] && cat == 'Book' ) { oTableRightCell.appendChild( document.createElement("BR") ); }
	   
   if( artist[curr] && cat == 'Music' ) { oTableRightCell.appendChild( document.createTextNode( 'by ' + artist[curr].nodeValue ) ); }
   if( artist[curr] && cat == 'Music' ) { oTableRightCell.appendChild( document.createElement("BR") ); }
   if( artist[curr] && cat == 'Music' ) { oTableRightCell.appendChild( document.createElement("BR") ); }

   if( price[curr]) { oTableRightCell.appendChild( document.createTextNode( 'List Price: ' + price[curr].nodeValue ) ); }
   if( price[curr]) { oTableRightCell.appendChild( document.createElement("BR") ); }
   if( price[curr]) { oTableRightCell.appendChild( document.createElement("BR") ); }

   if( cat ) { oTableRightCell.appendChild( document.createTextNode( 'Category: ' + cat ) ); }
   if( cat ) { oTableRightCell.appendChild( document.createElement("BR") ); }
   
   if( salesRank[curr] ) { oTableRightCell.appendChild( document.createTextNode( 'Sales Rank: #' + salesRank[curr].nodeValue ) ); }
   if( salesRank[curr] ) { oTableRightCell.appendChild( document.createElement("BR") ); }
   
   oTableRightCell.appendChild( document.createElement("BR") );

   /////// DISPLAY MUSIC DISC AND TRACKS IF POSSIBLE
   if( numDiscs.value.length ){
      var discInfoDiv = document.createElement("DIV");
      var listingTitleDiv = document.createElement("DIV");
      listingTitleDiv.setAttribute('class', 'mediumText');
      listingTitleDiv.appendChild( document.createTextNode( 'Discography' ) );
      listingTitleDiv.appendChild( document.createElement("BR") );
      discInfoDiv.appendChild( listingTitleDiv );
      
      ///// FOR EACH DISC - PRINT TITLE
      for( b = 0; b < numDiscs.value.length; b++ ){
          discNumber = xpathParse('@Number').evaluate(new ExprContext(numDiscs.value[b])).stringValue();
	  var discNumberDiv = document.createElement("DIV");
	  discNumberDiv.setAttribute('class', 'mediumText');
	  discNumberDiv.appendChild( document.createTextNode( 'Disc: ' + discNumber ));
	  discNumberDiv.appendChild( document.createElement("BR") );
	  discInfoDiv.appendChild( discNumberDiv );
	  
	  numTracks = xpathParse("Track/text()").evaluate(new ExprContext(numDiscs.value[b])).nodeSetValue();
	  var trackNameDiv = document.createElement("DIV");
	  ///// FOR EACH TRACK WITHIN A DISC - PRINT TITLE
	  for( c = 0; c < numTracks.length; c++ ){
      	       var trackName = numTracks[c].nodeValue;
	       trackNameDiv.appendChild( document.createTextNode( (c+1) + ') ' + trackName ) );
	       trackNameDiv.appendChild( document.createElement("BR") );	       
	  }
	  discInfoDiv.appendChild( trackNameDiv );
	  discInfoDiv.appendChild( document.createElement("BR") );
      }
      oTableRightCell.appendChild( discInfoDiv );
   }
	  
   /////// DISPLAY EDITORIAL REVIEW
   if( edReviewSource[curr] && edReviewContent[curr] ){
	var edReviewDiv = document.createElement("DIV");
	edReviewDiv.setAttribute('id', 'edReview' + curr);
	var edReviewTitle = document.createElement("DIV");
	edReviewTitle.setAttribute('class', 'mediumText');
	edReviewTitle.appendChild( document.createTextNode( 'Editorial Review from ' + edReviewSource[curr].nodeValue ) );
	edReviewDiv.appendChild( edReviewTitle );
	edReviewDiv.appendChild( document.createElement("BR") );
//	edReviewDiv.appendChild( document.createTextNode( edReviewContent[curr].nodeValue ) );
        edReviewDiv.innerHTML += edReviewContent[curr].nodeValue;
	edReviewDiv.appendChild( document.createElement("BR") );
	edReviewDiv.appendChild( document.createElement("BR") );
	oTableRightCell.appendChild( edReviewDiv );
   }

   ////// DISPLAY CUSTOMER REVIEWS AND RATINGS
   var custReviewsDiv = document.createElement("DIV");
   custReviewsDiv.setAttribute('class', 'mediumText');
   if( reviewAvgRating[curr] ) { custReviewsDiv.appendChild( document.createTextNode( 'Customer Reviews' ) ); }
   custReviewsDiv.appendChild( document.createElement("BR") );

   if( reviewAvgRating[curr] ){ 
   	var averageRating = reviewAvgRating[curr].nodeValue;
   	custReviewsDiv.appendChild( document.createTextNode( 'Average customer review rating: ' ) );

   	for( var p = 0; p < 5; p++ ){
		var starImg = document.createElement("IMG");
		if( averageRating >= 1 ){
	    		starImg.setAttribute('src', redStar100.src);
		}
		else if( averageRating == 0.5 ){
	     		starImg.setAttribute('src', redStar50.src);
		}
		else if( averageRating <= 0 ){
	     		starImg.setAttribute('src', redStar0.src);
		}
		custReviewsDiv.appendChild( starImg );
		averageRating = averageRating - 1;
   	} 
   	custReviewsDiv.appendChild( document.createElement("BR") ); 
   	custReviewsDiv.appendChild( document.createElement("BR") ); 
   }

   oTableRightCell.appendChild( custReviewsDiv );

   if( reviewRating[curr] && reviewSummary[curr] && reviewContent[curr] ){
        for( var i = curr; i < reviewRating.length; i++) {
	     var reviewDiv = document.createElement("DIV");	
	    
	     var reviewTitleDiv = document.createElement("DIV");
	     var reviewToggleId = "reviewToggle" + ( ( uniqueDivId * 10 ) + i );
	     var reviewToggleLink = document.createElement("A");
	     reviewToggleLink.appendChild( document.createTextNode("+/- ") );
	     reviewToggleLink.setAttribute("href", "#");
	     reviewToggleLink.setAttribute('onclick', "toggleDiv\(" + reviewToggleId  + "\)\; return false\;");
	     reviewTitleDiv.appendChild( reviewToggleLink );
	     reviewTitleDiv.appendChild( document.createTextNode( reviewSummary[i].nodeValue ) );
	     reviewTitleDiv.setAttribute('class', 'mediumText');
	     reviewDiv.appendChild( reviewTitleDiv );

	     var reviewRatingDiv = document.createElement("DIV");
	     var thisRating = reviewRating[i].nodeValue;
	     
	     for( var y = 0; y < 5; y++ ){
	       var starImg = document.createElement("IMG");
	       if( thisRating >= 1 ){
	          starImg.setAttribute('src', redStar100.src);
	       }
	       else if( thisRating == 0.5 ){
	          starImg.setAttribute('src', redStar50.src);
	       }
	       else if( thisRating <= 0 ){
	          starImg.setAttribute('src', redStar0.src);
	       }
	       reviewRatingDiv.appendChild( starImg );
	       thisRating = thisRating - 1;
	     } 
	     reviewDiv.appendChild( reviewRatingDiv );
	     reviewDiv.appendChild( document.createElement("BR") );

 	     var innerReviewDiv = document.createElement("DIV");
	     innerReviewDiv.setAttribute('id', reviewToggleId );
	     var embeddedReviewDiv = document.createElement("DIV");
//	     embeddedReviewDiv.appendChild( document.createTextNode( reviewContent[i].nodeValue ) );
             embeddedReviewDiv.innerHTML += reviewContent[i].nodeValue;
	     embeddedReviewDiv.appendChild( document.createElement("BR") );
	     embeddedReviewDiv.appendChild( document.createElement("BR") );
	     innerReviewDiv.appendChild( embeddedReviewDiv );
	     reviewDiv.appendChild( innerReviewDiv );
	     
	     oTableRightCell.appendChild( reviewDiv );
       }
   }

   ////// DISPLAY SIMILAR PRODUCT LINKS
   if( simProductAsin[curr] && simProductTitle[curr] ){
       var simProductDiv = document.createElement("DIV");
       simProductDiv.setAttribute('class', 'mediumText');
       simProductDiv.appendChild( document.createTextNode( 'Similar Items :') );
       oTableRightCell.appendChild( simProductDiv );
       
       for( var j = curr; j < simProductAsin.length; j++ ){
	 var currLink = document.createElement("A");
	 currLink.setAttribute("href", "#");
	 var prodTitle = document.createTextNode( simProductTitle[j].nodeValue ); 
	 currLink.setAttribute('onclick', "userbox.value\=\'lookup -id " + simProductAsin[j].nodeValue + "\'\; userbox.focus\(\)\; return false\;");
	 currLink.appendChild( prodTitle );
	 oTableRightCell.appendChild( currLink );
	 oTableRightCell.appendChild( document.createElement("BR") );
       }
   } 
  
   oTableHeadRow.appendChild( oTableLeftCell );
   oTableHeadRow.appendChild( oTableRightCell );
   oTableBody.appendChild( oTableHeadRow );
   oTable.appendChild( oTableBody );

   /////////// THE ENTIRE TABLE IS READY - ADD IT TO COLLAPSIBLE DIVS
   var containerDiv = document.createElement("DIV");
   containerDiv.setAttribute('align', 'left');   
   var resultsToggleLink = document.createElement("A");
   resultsToggleLink.appendChild( document.createTextNode("+/- ") );
   resultsToggleLink.setAttribute("class", "mediumText");
   resultsToggleLink.setAttribute("href", "#");
   resultsToggleLink.setAttribute('onclick', "toggleDiv\(Encap" + uniqueDivId + "\)\; return false\;");
   containerDiv.appendChild( resultsToggleLink );
   
   var encapsulate = document.createElement("DIV");
   var EncapId = "Encap" + uniqueDivId;
   encapsulate.setAttribute("id", EncapId );
   var appendedDiv = document.createElement("DIV");
   appendedDiv.appendChild( oTable );
   containerDiv.appendChild( encapsulate );
   encapsulate.appendChild( appendedDiv );
   
   /////////// FINALLY, ADD TO CLI RESULT DIV
   $('cliResult').appendChild( containerDiv );
   
   ////// SLIDE UP 'LOADING', SLIDEDOWN RESULTS, SMOOTHLY TRANSITION IMAGE OPACITY FROM 0 to 100%
   Effect.SlideUp('lo');
   Effect.SlideDown('cliResult');
   new Effect.Opacity( 'image0', { duration: 5.0, transition: Effect.Transitions.linear, from: 0.0, to: 1.0 });
}


//////////////////////////////////////////////////////////
// This function is called at the end of the asynchronous
// ItemSearch operation call, to parse XML and convert to 
// a W3CDOM Table.
//////////////////////////////////////////////////////////
function itemSearchResponse(originalRequest){       
   
   ///// DISABLE XPATH & XSLT DIALOG BOX
   xpathdebug = false;
   xsltdebug = false;

   var myXML = new ExprContext(originalRequest.responseXML);

   ///// PARSE OUT ALL THE ARGUMENTS THAT ARE ECHOED BACK IN THE REQUEST
   var arguments = xpathParse("//OperationRequest/Arguments/Argument").evaluate(myXML);
   var argumentHash = new Object;
   for( a = 0; a < arguments.value.length; a++ ){
      argumentName =  xpathParse('@Name').evaluate(new ExprContext(arguments.value[a])).stringValue(); 
      argumentValue = xpathParse('@Value').evaluate(new ExprContext(arguments.value[a])).stringValue();
      argumentHash[argumentName] = argumentValue;
   }

   /////// CHECK TO SEE IF THE RESPONSE IS VALID, AND DISPLAY APPROPRIATE ERROR MESSAGE(S)
   var isValid = xpathParse("/ItemSearchResponse/Items/Request/IsValid/text()").evaluate(myXML).nodeSetValue();
   if( isValid[0].nodeValue == "False" ){
      var errorMsgs =  xpathParse("/ItemSearchResponse/Items/Request/Errors/Error/Message/text()").evaluate(myXML).nodeSetValue();
      for( var x = 0; x < errorMsgs.length; x++ ){
         var errDiv = document.createElement("DIV");
         var err = document.createTextNode('ERROR: ' + errorMsgs[x].nodeValue );
	 errDiv.setAttribute('class', 'errorText');
	 errDiv.appendChild(err);
      }
      errDiv.appendChild( document.createElement("BR") );
      errDiv.appendChild( document.createElement("BR") );
      errDiv.appendChild( document.createTextNode("Type 'search -help' for more information") );
      $('cliResult').appendChild( errDiv );
      Effect.SlideUp('lo');
      Effect.SlideDown('cliResult');
      return false;
   }
   
   //////// PARSE RESULTING XML FOR RELEVANT INFO AND STORE IN LOCAL ARRAYS

   var asins = xpathParse("/ItemSearchResponse/Items/Item/ASIN/text()").evaluate(myXML).nodeSetValue();
   //   var author = xpathParse("/ItemSearchResponse/Items/Item/ItemAttributes/Author/text()").evaluate(myXML).nodeSetValue();
   //   var artist = xpathParse("/ItemSearchResponse/Items/Item/ItemAttributes/Artist/text()").evaluate(myXML).nodeSetValue();
   var title = xpathParse("/ItemSearchResponse/Items/Item/ItemAttributes/Title/text()").evaluate(myXML).nodeSetValue();
   var price = xpathParse("/ItemSearchResponse/Items/Item/ItemAttributes/ListPrice/FormattedPrice/text()").evaluate(myXML).nodeSetValue();
   var salesRank = xpathParse("/ItemSearchResponse/Items/Item/SalesRank/text()").evaluate(myXML).nodeSetValue();
   var mediumImages =  xpathParse("/ItemSearchResponse/Items/Item/MediumImage/URL/text()").evaluate(myXML).nodeSetValue();
   var totalResults = xpathParse("/ItemSearchResponse/Items/TotalResults/text()").evaluate(myXML).nodeSetValue();
   var totalPages = xpathParse("/ItemSearchResponse/Items/TotalPages/text()").evaluate(myXML).nodeSetValue();
   var nodeSetSize = title.length;

   ////// CONSTRUCT THE TABLE OBJECT
   var curr = 0;
   var oTable = document.createElement("TABLE");
   oTable.border = 0;
   oTable.setAttribute('width', '95%');
   oTable.id = "tabRes";
   var oTableBody = document.createElement("TBODY");

   ////// TABLE HEADER INFORMATION
   oTableHeadRow = document.createElement("TR");
   oTableHeadLine = document.createElement("TD");
   if( argumentHash['SearchIndex'] ){
       oTableHeadLine.appendChild( document.createTextNode( 'Search Index: ' + argumentHash['SearchIndex']  ) );
       oTableHeadLine.appendChild( document.createElement("BR") );
   }
   oTableHeadLine.appendChild( document.createTextNode( 'Total Results: ' + totalResults[curr].nodeValue  ) );
   oTableHeadLine.appendChild( document.createElement("BR") );
   oTableHeadLine.appendChild( document.createTextNode( 'Total Pages: ' + totalPages[curr].nodeValue  ) );
   oTableBody.appendChild( oTableHeadLine );
   
  /////// SPECIFY TABLE CONSTANTS
   var itemsPerRow = 5; 
   var cell_width = 95 / itemsPerRow;
   cell_width += '%';
   
   ///// RECURSIVELY APPEND ELEMENTS TO THE TABLE FOLLOWING THE ROW / COL SPECIFICATION
   for(var curr, j = 0; j < nodeSetSize / itemsPerRow; j++){
        oCurrRow = document.createElement("TR");
	
        for( var i = 0; i < itemsPerRow; i++){
	   oCurrCell = document.createElement("TD");
	   oCurrCell.setAttribute('width', cell_width);
        
           prodCellImage = document.createElement("TR");
	   
	   //////// DISPLAY THE PRODUCT IMAGE
	   if( asins[curr] ) {
	       var imageDiv = document.createElement("DIV");
	       imageDiv.setAttribute('class', 'img-dec');
	       var imgId = "image" + (uniqueDivId * 10) + curr;
	       imageDiv.setAttribute('id', imgId);

	       setGlobalASIN( asins[curr].nodeValue );
	       
//	       prodCellImage.appendChild( document.createElement("BR") );
	       var currImg = new Image();

	       if( mediumImages[curr] ){
	         currImg.src = mediumImages[curr].nodeValue;
	       }
	       else{
	         currImg.src = notAvail.src;
	       }
              
	       var currLink = document.createElement("A");
	       currLink.setAttribute("href", curr);
	       var currAsin = asins[curr].nodeValue;
	       currLink.setAttribute("onMouseOver", "handleOverProduct\(" + (uniqueDivId*10) + curr + "\)\; return true\;");
	       currLink.setAttribute("onMouseOut", "handleOutProduct\(" + (uniqueDivId*10) + curr + "\)\; return true\;");
	        
	       newImage = document.createElement("IMG");
	       newImage.setAttribute('src', currImg.src );
	       newImage.setAttribute('onclick', "userbox.value\=\'lookup -id " + asins[curr].nodeValue + "\'\; userbox.focus\(\)\; return false\;");
	       
	       currLink.appendChild( newImage );
	       imageDiv.appendChild( currLink );
	       prodCellImage.appendChild( imageDiv );
	       prodCellImage.appendChild( document.createElement("BR") );
	   }
	   
	   attribCell = document.createElement("TR");
	   
	   //////// DISPLAY BASIC ITEM ATTRIBUTES
	   if( title[curr]) { attribCell.appendChild( document.createTextNode( (ASINdex - 1) + ')  ' + title[curr].nodeValue ) ); }
           if( title[curr]) { attribCell.appendChild( document.createElement("BR") ); }
	   
           //	   if( author[curr]) { oCurrCell.appendChild( document.createTextNode( 'Author: ' + author[curr].nodeValue ) ); }
           //      if( author[curr]) { oCurrCell.appendChild( document.createElement("BR") ); }	   
           //	   if( artist[curr]) { oCurrCell.appendChild( document.createTextNode( 'Artist: ' + artist[curr].nodeValue ) ); }
           //      if( artist[curr]) { oCurrCell.appendChild( document.createElement("BR") ); }
	   
	   if( price[curr]) { attribCell.appendChild( document.createTextNode( 'Price: ' + price[curr].nodeValue ) ); }
           if( price[curr]) { attribCell.appendChild( document.createElement("BR") ); }
	   
	   if( salesRank[curr] && salesRank[curr].nodeValue <= 100) { attribCell.appendChild( document.createTextNode( 'Sales Rank: #' + salesRank[curr].nodeValue ) ); }
           if( salesRank[curr] && salesRank[curr].nodeValue <= 100) { attribCell.appendChild( document.createElement("BR") ); }
	  
	   curr++;
	   oCurrCell.appendChild( prodCellImage );
	   oCurrCell.appendChild( attribCell );
	   oCurrRow.appendChild( oCurrCell );
	}
        oTableBody.appendChild( oCurrRow );
   }
   oTable.appendChild( oTableBody );

   /////////// THE ENTIRE TABLE IS READY - ADD IT TO COLLAPSIBLE DIVS
   var containerDiv = document.createElement("DIV");
   containerDiv.setAttribute('align', 'left');   
   var resultsToggleLink = document.createElement("A");
   resultsToggleLink.appendChild( document.createTextNode("+/- ") );
   resultsToggleLink.setAttribute("class", "mediumText");
   resultsToggleLink.setAttribute("href", "#");
   resultsToggleLink.setAttribute('onclick', "toggleDiv\(Encap" + uniqueDivId + "\)\; return false\;");
   containerDiv.appendChild( resultsToggleLink );
   
   var encapsulate = document.createElement("DIV");
   var EncapId = "Encap" + uniqueDivId;
   encapsulate.setAttribute("id", EncapId );
   var appendedDiv = document.createElement("DIV");
   appendedDiv.appendChild( oTable );
   containerDiv.appendChild( encapsulate );
   encapsulate.appendChild( appendedDiv );

   ///// FINALLY, APPEND TO CLI RESULT DIV
   $('cliResult').appendChild( containerDiv );
   
   /////// POST PROCESS - SLIDEUP 'LOADING', SLIDEDOWN RESULTS, CHANGE OPACITY FOR EACH IMAGE DISPLAYED.
   Effect.SlideUp('lo');
   Effect.SlideDown('cliResult');
   for( op = 0; op < nodeSetSize; op++ ){
     var imgToOpacify = "image" + (uniqueDivId*10) + op;
     new Effect.Opacity( imgToOpacify, { duration: 0.2, transition: Effect.Transitions.linear, from: 1.0, to: 0.5 });
   }
}


//////////////////////////////////////////////////////
// Function to handle default response for functions
// To Be Finalized - Invoked in God Mode
//////////////////////////////////////////////////////
function defaultResponse( originalRequest ){
   responseFrame = document.createElement("IFRAME");
   responseFrame.setAttribute ('src', originalRequest); 
   responseFrame.setAttribute('width', '85%');
   responseFrame.setAttribute('height', '80%');
   
   var requestLink = document.createElement("A");
   requestLink.appendChild( document.createTextNode( originalRequest ) );
   requestLink.setAttribute( "href", originalRequest );
   
   $('cliResult').innerHTML = '';
   if( godMode ){
       $('cliResult').appendChild( requestLink );
   }
   $('cliResult').appendChild( responseFrame );
   Effect.SlideUp('lo');
   Effect.SlideDown('cliResult');
}


/////////////////////////////////////////////////////
// Function to parse the command line arguments
// for appropriate flags and return a populated hash
/////////////////////////////////////////////////////
function parseCommandLine( argsv ){
  
  var paramHash = new Object;
  var i = 1;       
  var j = 0;
  var arg;
  var startsWithMinus = /^-/;
 
  paramHash['Operation'] = operationMap( argsv );
  paramHash['OtherParams'] = '';

  while ( i < argsv.length && argsv[i].match(startsWithMinus) ){ 

  	arg = argsv[i++]; 
       
   //// SUBSTITE $INT WITH GLOBAL ASIN
	var startsWithDollar = /^\$/;
	if( i < argsv.length && argsv[i].match(startsWithDollar) ){
            argsv[i] = getGlobalASIN( argsv[i] ); 
	}
	
	//// PARSE KEY / VALUE PAIRS FOR ALL OPERATIONS
	if ( arg == "-keywords" || arg == "-Keywords" || arg == "-k" ){
	    paramHash['Keywords'] = argsv[i];
	    paramHash['OtherParams'] += '&Keywords=' +  argsv[i++];
	}

 	else if ( arg == "-index" || arg == "-Index" || arg == "-i" || arg == "-SearchIndex" ){
	    var searchInd = convertCase(argsv[i++]);
	    paramHash['SearchIndex'] = searchInd;
	    paramHash['OtherParams'] += '&SearchIndex=' +  searchInd;
	}
       
	else if ( arg == "-response" || arg == "-Response" || arg == "-r" || arg == "-ResponseGroup" ){
	   paramHash['ResponseGroup'] = argsv[i];
	   paramHash['OtherParams'] += '&ResponseGroup=' +  argsv[i++];
	}

	else if ( arg == "-sort" || arg == "-Sort" || arg == "-s"){
	   paramHash['Sort'] = argsv[i];
	   paramHash['OtherParams'] += '&Sort=' + argsv[i++];
	}
	
	else if ( arg == "-page" || arg == "-Page" || arg == "-p"){
	   paramHash['ItemPage'] = argsv[i];
	   paramHash['OtherParams'] += '&ItemPage=' + argsv[i++];
	}

	else if ( arg == "-id" || arg == "-Id" || arg == "-ItemId"){
	   if( paramHash['Operation'] == "CartCreate" || paramHash['Operation'] == "CartAdd" ){
	       paramHash['Item.1.ASIN'] = argsv[i];
	       paramHash['OtherParams'] += '&Item.1.ASIN=' + argsv[i++];
	   }
	   else{
	      paramHash['ItemId'] = argsv[i];
	      paramHash['OtherParams'] += '&ItemId=' + argsv[i++];
	   }
	}

	else if ( arg == "-q" || arg == "-Q" || arg == "-Quantity" || arg == "-quantity" ){
	   paramHash['Item.1.Quantity'] = argsv[i];
	   paramHash['OtherParams'] += '&Item.1.Quantity=' + argsv[i++];
	}

	else if ( arg == "--help" || arg == "--Help" || arg == "-h" || arg == "-help" || arg == "-Help" ){
	   paramHash['Help'] = 'Yes';
	   paramHash['OtherParams'] += '&Help=' + argsv[i++];
	}
	
	//// IGNORE CART OPERATION 'ACTION' PARAMETERS
	else if ( arg == "-add" || arg == "-Add" || arg == "-create" || arg == "-Create" || arg == "-view" || arg == "-View" ){
	   paramHash['Append'] = 1;
	}
	
	else if ( arg == "--append" || arg == "--Append" || arg == "-append" || arg == "-Append" ){
	   paramHash['Append'] = 1;
	   paramHash['OtherParams'] += '&Append=1';
	   globalAppendCount++;
	   uniqueDivId++;
	}
	else {
	   paramHash['OtherParams'] += '&';
	   var chopFront = arg.split('-');
	   paramHash['OtherParams'] += convertCase(chopFront[1]);
	   paramHash['OtherParams'] += '=';
	   paramHash['OtherParams'] += argsv[i++];
	   //window.alert( paramHash['OtherParams'] );
 	}
  }	

  if( !paramHash['SearchIndex'] && paramHash['Operation'] == "ItemSearch" ){
      paramHash['OtherParams'] += '&SearchIndex=Music';
      paramHash['SearchIndex'] = 'Music';
  }

  if( !paramHash['Item.1.Quantity'] && paramHash['Operation'] == "CartAdd" ){
      paramHash['OtherParams'] += '&Item.1.Quantity=1';
      paramHash['Item.1.Quantity'] = 1;
  }  

  if( !paramHash['ResponseGroup'] ){
      if( paramHash['Operation'] == "ItemLookup" ){
          paramHash['OtherParams'] += '&ResponseGroup=Large';
          paramHash['ResponseGroup'] = 'Large'; 
      }
      else if( paramHash['Operation'] ==  "ItemSearch" ){
         paramHash['OtherParams'] += '&ResponseGroup=Medium';
         paramHash['ResponseGroup'] = 'Medium'; 
      }
      else if( paramHash['Operation'] == "Cart" ){
	   	paramHash['OtherParams'] += '&ResponseGroup=Cart';
	  		paramHash['ResponseGroup'] = 'Cart';
      }
  }

  return paramHash;
}


////////////////////////////////////////////////////
// Function to validate if the operation and its 
// parameters are valid, sets default values if  
// required, and returns true or false appropriately
////////////////////////////////////////////////////
function validateOperation( cmdHash ){ 

   var op = cmdHash['Operation'];

   if( op == "ItemSearch" ){
       if( cmdHash['SearchIndex'] ) 
      	   cmdHash['IsValid'] = 'Yes';
       else
          cmdHash['IsValid'] = 'No';
   }
   else if( op == "ItemLookup" ){
       if( cmdHash['ItemId'] )
           cmdHash['IsValid'] = 'Yes';
       else
           cmdHash['IsValid'] = 'No';
   }
   else if( op == "CartCreate" ){
       cmdHash['IsValid'] = 'Yes';
   }
   else if( op == "CartAdd" ){
     if( cmdHash['Item.1.ASIN'] )
         cmdHash['IsValid'] = 'Yes';  
     else
         cmdHash['IsValid'] = 'No';
   }
   else if( op == "CartGet" ){
     cmdHash['IsValid'] = 'Yes';
   }
   else if( op == "CartPurchase" ){
     cmdHash['IsValid'] = 'Yes';
   }
   else{
       cmdHash['IsValid'] = 'No';
   }

   //// GOD MODE OVERRIDE
   if( godMode ){
       cmdHash['IsValid'] = 'Yes';
   }
   
   return cmdHash;
}


//////////////////////////////////////////////////////////
// Function that maps CLI operation aliases to actual AWS
// operation names
//////////////////////////////////////////////////////////
function operationMap ( argsv ){

  var operation = argsv[0];
  var paramOne = argsv[1];

  if( operation == "ItemSearch" || operation == "Search" || operation == "search" ){
  	return "ItemSearch";
  }
  else if ( operation == "ItemLookup" || operation == "Lookup" || operation == "lookup" ){
  	return "ItemLookup";
  }
  else if ( operation == "Style" || operation == "style" || operation == "SwitchStyle" ){
       return "SwitchStyle";
  }
  else if ( operation == "Cart" || operation == "cart" ){
       if( paramOne == "-create" || paramOne == "-Create" ){
         return "CartCreate";
       }
       else if( paramOne == "-add" || paramOne == "-Add" ){
	 return "CartAdd";
       }
       else if( paramOne == "-view" || paramOne == "-View" ){
	 return "CartGet";
       }
       else if( paramOne == "-clear" || paramOne == "-Clear" ){
         return "CartCreate";
       }
       else if( paramOne == "-purchase" || paramOne == "-Purchase" || paramOne == "-checkout" || paramOne == "-Checkout" ){
         return "CartPurchase";
       }
       return "CartCreate";
  }
  else {
     return operation;
  }
}

//////////////////////////////////////////////////////
// Function that converts whitespace within quotes 
// to %20, so it can be passed in AJAX Request
//////////////////////////////////////////////////////
function convertWhiteSpace(  args   ){
 
  var quoteLoc = [];
  var quoteIndex = 0;

  for( var i =0; i < args.length; i++ ){
      if( args[i] == "\'" ){
        quoteLoc[quoteIndex++] = i;
      }
  }

  if ( (quoteIndex % 2) != 0 ){
  	window.alert("Your command has mismatched quotation marks. Code:" + quoteIndex );
  }
  else {
     var newArgs = new String();
     var n = 0;
     var x = 0;
     
     for( ; x < args.length; x++){
	     if( args[x] == " " && x > quoteLoc[n] && x < quoteLoc[n + 1] ){
	        newArgs += "%20";
	     } 
	     else{
	        newArgs += args[x];
	     }
	     if( x == quoteLoc[n + 1]   ){
	       n = n + 2;
	     }
	 }
  }
  return newArgs;
}

//////////////////////////////////////////////////////
// Function to generate and display documentation for
// specified Operation.
/////////////////////////////////////////////////////
function Help( operation ){
   
  $('cliResult').innerHTML = clearButtonHTML();
  var helpUrl = 'DOCS/' + operation['Operation'] + 'Help';
  var helpPars = '';
  var helpRequest = new Ajax.Request( helpUrl, {method: 'get', parameters: helpPars, onComplete: displayHelp} );

}

function displayHelp( originalRequest ){
  $('cliResult').innerHTML += originalRequest.responseText;
  Effect.SlideDown('cliResult');
}



///////////////////////////////////////////////////////////////
// Miniscule self-explanatory / hacky reusable functions below
///////////////////////////////////////////////////////////////
function toggleDiv( ID ){
  if( $(ID).style.display == 'none' ){
    Effect.SlideDown(ID);
  }
  else{
    Effect.SlideUp(ID);
  }
}

function handleOver() { 
 document.imgName.src=img_on.src;
}

function handleOut() {
 document.imgName.src=img_off.src;
}

function handleOverProduct( num ) {
 var imgId = "image" + num;
 new Effect.Opacity( imgId, { duration: 0.5, transition: Effect.Transitions.linear, from: 0.5, to: 1.0 }); 
}

function handleOutProduct( num ) {
  var imgId = "image" + num;
  new Effect.Opacity( imgId, { duration: 0.5, transition: Effect.Transitions.linear, from: 1.0, to: 0.5 });  
}
  
function clearButtonHTML() {
 var minButton = '\<a href=# id=closeresults onMouseOver=\"handleOver\(\)\;return true\;\" onMouseOut=\"handleOut\(\)\;return true\;\"\>\<img name=imgName align=right width=17 height=15 border=0 src=\"IMAGES\/minus2.jpg\" onclick=\"new Effect.SlideUp\(\'cliResult\'\)\; userbox.focus\(\)\; return false\;\"\>\<\/a\>';
 return minButton;
}

function convertCase( text ){
  var firstChar = text;
  firstChar = firstChar[0].toUpperCase();    
  var cased = firstChar + ((text).substr(1));
  return cased;
}

function reInit(){
   window.scrollTo(0, 2000000000);
   userbox.focus();
   userbox.value = "";
   return;
}

/////// FUNCTIONS TO MANIPULATE THE GLOBAL ARRAY OF ASINs
function setGlobalASIN( ASIN ){
 globalArrayOfASINs[ASINdex++] = ASIN;
}

function getGlobalASIN( indexRef ){
  var ASIN;
  var chopFront = indexRef.split('$');
  if( chopFront[1] < globalArrayOfASINs.length){
     ASIN = globalArrayOfASINs[chopFront[1]];
  }
  else{
     ASIN = '0000000000';
  }
  return ASIN;	       
}
