/**
*
*
* @FileName: mab.js
* @Author: Fabio Serra AKA Faser - faser@faser.net
* @Revision History:
* 07/09/2003 - Added search with google, tabpanel to display more information
* 02/09/2003 - Bug Fixing and some constant to set default value for 
* remote and local version, end user and developer version
* 22/07/2003 - Modified Amazon URL for new locale and API 
* 21/03/2003 - Use DOMParse on responseText as workaround to Moz 1.3
* 21/03/2003 - printDoc() enabled
* 19/03/2003 - Faser - Moved checkLoad function inside connection()
* Added possibility to abort request with ESC.
*/

const MAB_VERSION = "1.1.0.0";

//locally | remotely 
const MAB_RUN = "remotely";

//user | developer 
const MAB_RELEASE = "user";

//Amazon Web Service URL for each locale
const AWSURL = {};
	  AWSURL["us"] = "http://xml.amazon.com/onca/xml3";
	  AWSURL["uk"] = "http://xml-eu.amazon.com/onca/xml3";
	  AWSURL["de"] = "http://xml-eu.amazon.com/onca/xml3";
	  AWSURL["jp"] = "http://xml.amazon.com/onca/xml3";
	  AWSURL["fr"] = "";
	  AWSURL["ca"] = "";

//Developer Token
const DEVT = "D3MAIAYX2Q6JLY";	

//Associate ID
const ASSID = {};
	  ASSID["us"] = "faser-20";
	  ASSID["uk"] = "faser-21";
	  ASSID["de"] = "faser0f-21";
	  ASSID["jp"] = "webservices-20";
	  ASSID["fr"] = "webservices-20";
	  ASSID["ca"] = "webservices-20";
		
//Amazon HomePage URL
const AMAZONURL = {};
	  AMAZONURL["us"] = "http://www.amazon.com";
	  AMAZONURL["uk"] = "http://www.amazon.co.uk";
	  AMAZONURL["de"] = "http://www.amazon.de";
	  AMAZONURL["jp"] = "http://www.amazon.co.jp";
	  AMAZONURL["fr"] = "http://www.amazon.fr";
	  AMAZONURL["ca"] = "http://www.amazon.ca";	
	  
//Google HomePage URL
const GOOGLEURL = {};
	  GOOGLEURL["us"] = "http://www.google.com";	  
	  GOOGLEURL["uk"] = "http://www.google.co.uk";
	  GOOGLEURL["de"] = "http://www.google.de";
	  GOOGLEURL["jp"] = "http://www.google.jp";
	  GOOGLEURL["fr"] = "http://www.google.fr";
	  GOOGLEURL["ca"] = "http://www.google.ca"; 
	  
//Output Format
f ="xml";

//My Document List Obj
myDoc = new Array();
	
/*Settings*/

//Locally
if(MAB_RUN == "locally") {
	//Amazon Search Type
	searchType = "heavy";
	//Connect by a Proxy?
	aProxy = false;
} else if(MAB_RUN == "remotely"){
	//Amazon Search Type
	searchType = "lite";
	//Connect by a Proxy?
	aProxy = true;
}

//My Search Type
mySearchType = "default";
//Max Result from each search
maxResults = 10;
//Default Proxy URL
aProxyUrl = "gateway.cfm";

//Activate Debug panel
if(MAB_RELEASE == "user") {
	debugMode = false;
}else{
	debugMode = true;
}
		
//Create a new list after each search
newList = false;
//TimeOut Connection
timeOut = 120;
//Page to call
page = 1;
//Default Locale
locale = "us";	  	

//Main
function main() {
	/*	Get a reference to GUI Element 	*/
	//Search Mode PopUp
	guiModeType = document.getElementById('mode-popup');
	//Search Criteria Pop-Up 
	guiCriteria = document.getElementById('search-popup');
	//Sort by
	guiSortType = document.getElementById('sort-popup');
	//Search Input
	guiFindText = document.getElementById('find-text');
	//Progress Bar
	guiMeter = document.getElementById('meter');
	//General Status Bar Message
	guiStatusBar = document.getElementById('out-status');
	//Nr Record fetched status bar message
	guiRecordStatus = document.getElementById('record-status');
	//Search Button
	searchBtn = document.getElementById('find-button');
	//Next Button
	nextBtn = document.getElementById('next-btn');
	//Clear Button
	clearBtn = document.getElementById('clear-btn');
	//Abort Connection
	abortIcon = document.getElementById('abort-icon')
	//Comments Button
	commentBtn = document.getElementById('comment-button');
	//Main Result Tree
	guiMainTree = document.getElementById('result-tree');
	//List result
	guiListTree = document.getElementById('list-tree');
	//Details Box
	guiDetailBox = document.getElementById('detail-box');
	//Price Box
	guiPriceBox = document.getElementById('price-box');
	//Image
	guiTheImg = document.getElementById('ImageUrlMedium');
	//Comment iframe
	guiTheComment = window.frames[0].document.getElementById('commentOutput');
	//All Info
	guiTheInfo = window.frames[1].document.getElementById('allInfoOutput');
	//Debug Output	
	guiDebugOut = document.getElementById('debug-output');
	guiDebugSplitter = document.getElementById('debug-splitter');
	if(MAB_RELEASE == "user") {
		guiDebugOut.setAttribute('hidden','true');
		guiDebugSplitter.setAttribute('hidden','true');
	}	
	//Image
	guiImageSmall = document.getElementById('ImageUrlMedium');
	//The id of these boxes have the same name as amazon tags
	detRef = new Array("Author","Artist","ProductName","Manufacturer","ReleaseDate","ListPrice","OurPrice","UsedPrice");
	guiDetRef = new Array();
	for(var i=0;i<detRef.length;i++){
		guiDetRef[i] = document.getElementById(detRef[i]);
	}	
	
	//Focus on Search textbox
	window.focus();
	guiFindText.focus();
	
}


//If I change locale I need to create a new myAmaz
//This is a temporary work around. myAmaz Object can contain document only
//from one locale. I have to implement a way to store items from different locale.

function changeLocale(newLocale) {
	locale = newLocale;
	if(typeof myAmaz != 'undefined') {
			var count = 0;
			for(var idx in myDoc) {
				count++;
			}
			var nr = count+1;
			myDoc["Saved_"+nr] = myAmaz;
			myAmaz = new AmazonResult();
			clearAll();
	}	
}

//Amazon Web Service URL to call
function getAWSUrl() {
	if(aProxy == true) {
		return aProxyUrl;
	}else{
		return AWSURL[locale];
	}	 
}
	

function getSearchBy() {
	//The search type Keyword | Asin etc
	return searchBy = guiCriteria.selectedItem.getAttribute('value');
}

function getProductLine() {
	//Check Locale
	var tmp = guiModeType.selectedItem.getAttribute('value');
	switch(locale) {
		case "us":
			return tmp;
			break;
		
		case "uk":
			if(tmp == "videogames") return "video-games-uk";
			if(tmp == "music" || tmp == "classical") {
				return tmp;
			} else {
				return tmp+"-uk";
			}
			break;
			
		case "de":
			if(tmp == "videogames") return "video-games-de";
			if(tmp == "electronics") return "ce-de";
			if(tmp == "magazines") return "magazines-de";
			return tmp+"-de";
			break;
		
		case "jp":
			return tmp+"-jp";
			break;	
		
		default: return guiModeType.selectedItem.getAttribute('value');
	
	}
}

function getSortType() {
	return sortType = guiSortType.selectedItem.getAttribute('value');
}

function getInput() {
	if(guiFindText.value != "") {
		return guiFindText.value;
	}else{
		return false;	
	}	
}

function removeRows() {
	while(guiListTree.hasChildNodes()) {
		guiListTree.removeChild(guiListTree.lastChild);
	}
}

//Delete selected row from current list
function deleteRow(idx) {
	if(idx == -1) {
		return false;
	} else {	
		var theRows = guiListTree.getElementsByTagName('treerow');
		var amazPK = theRows[idx].getAttribute('id');
		var res = myAmaz.deleteRow(amazPK);
		//Remove Row from the result-tree
		if(res)	 {
			//Remove Row and clear comment and textbox
			clearTextBox();
			clearComment();
			clearImage();
			guiListTree.removeChild(theRows[idx].parentNode);
			//Set Focus on previous element
			setFocusOnList(idx-1);
			//Update Label
			guiRecordStatus.setAttribute('label',"Total Record Retrived: "+ myAmaz.getNrRecordParsed()+" ("+myAmaz.getNrRecord()+" in list)");
		}		
	}

}


function clearAll() {
	removeRows();
	clearTextBox();
	clearStatusBar();
	clearComment();
	clearImage();
	if(myAmaz.xmlDoc) myAmaz.xmlDoc = null;
	nextBtn.setAttribute('disabled','true');
	clearBtn.setAttribute('disabled','true');
	commentBtn.setAttribute('disabled','true');
	
}



function clearTextBox() {
	var txtInput =  document.getElementsByTagName('textbox');
	for(var i=0;i<txtInput.length;i++) {
		txtInput[i].setAttribute('value','');
		
	}
}

function clearStatusBar() {
	guiStatusBar.setAttribute('label','');
	guiRecordStatus.setAttribute('label','');
}

function clearComment() {
	//First Panel
	guiTheComment.innerHTML = "";
	//Second Panel
	guiTheInfo.innerHTML = "";
}

function clearImage() {
	guiImageSmall.setAttribute('src','');
}

function clearDebug() {
	guiDebugOut.value = "";
}

function changeStatus() {
	//Search
	searchBtn.setAttribute('disabled','false');
	//Next
	nextBtn.setAttribute('disabled','true');
}

function setDebugMode(cmd) {
	if(cmd == 1) {
		debugMode = true;
		guiDebugOut.setAttribute('hidden','false');
	}else{
		guiDebugOut.hidden = true;
		guiDebugOut.setAttribute('hidden','true');
	}
	
}

function setFocusOnList(idx) {
	if(idx && idx == -1) {
		var pos = 0;
	}else{
		var pos = idx;
	}
	guiMainTree.view.selection.select(pos);
	guiMainTree.focus();
}

function printDebug(txt) {
	if(debugMode) {
		//Clear
		if(guiDebugOut.value.length > 5000) clearDebug();
		//Write
		guiDebugOut.value = txt +"\n" + guiDebugOut.value;
		return true;
	}else{
		return false;
	}
}



function setMeter(command) {
	switch(command) {
		case "start":
			guiMeter.setAttribute('mode','undetermined');
			if(typeof window.setCursor == "function") {
				window.setCursor('wait');
			}
		break;
		case "stop":
			guiMeter.setAttribute('mode','determined');
			if(typeof window.setCursor == "function") {
				window.setCursor('auto');
			}
		break;
	}	

}

function newDoc() {
	//Clear GUI
	removeRows();
	clearTextBox();
	clearStatusBar();
	setMeter('stop');
	clearComment();
	clearImage();
	nextBtn.setAttribute('disabled','true');
	clearBtn.setAttribute('disabled','true');
	guiFindText.focus();
	
	if(debugMode) clearDebug();

	//Create new Obj
	myAmaz = new AmazonResult();
}

function saveDoc() {
	if(typeof myAmaz == 'undefined') {
		alert('Current document can not be saved!');
		return false;
	}
		
	if(myAmaz.xmlDoc == null) {
		alert('Current document is empty');
		return false;
	}	
	
	var docSaved = window.prompt('Save current list as:');
	if(docSaved == "") {
		alert("Please, insert a name");
		saveDoc();
		return false;
	}
			
	if(docSaved) {
		var conf = true;
		for(var idx in myDoc) {
			if(idx == docSaved) {
				conf = confirm('Overwrite the document with the same name?');
				break;
			}
		}		
		
		if(conf) {
			myDoc[docSaved] = myAmaz;
		}else{
			saveDoc();
			return false;
		}
		
	}
}

function listSavedDoc() {
	window.open('mydoc.xul','Documents Saved','chrome,centerscreen,modal');
}

function openDoc(doc) {
	myAmaz = myDoc[doc];
	removeRows();
	nextBtn.setAttribute('disabled','true');
	myAmaz.createTree();
}

//Export Doc in XML - open a news browser window. You need to switch in view source. 
function exportDoc() {
	if(typeof myAmaz == 'undefined' || myAmaz.xmlDoc == null) {
		alert("No document to export");
		return false;
	}	
	
	var s = new  XMLSerializer();
	var str = s.serializeToString(myAmaz.xmlDoc);
	var param = "toolbar=no,status=no,menubar=yes,scrollbars=yes,resizable=yes,location=no,directories=no";
	ow = window.open("","Export",param);
	ow.document.open('text/xml');
	ow.document.write(str);
	ow.document.close();
	
	return true;
}


/* Not finished - very unstable*/
function nextRecord() {
	page++;
	var query = getInput();
	if(query) {
		var qString = getAWSUrl()+'?t='+ASSID[myAmaz.store]+'&dev-t='+DEVT+'&'+getSearchBy()+'='+escape(query)+'&mode='
		+getProductLine()+'&sort='+getSortType()+'&type='+searchType+'&page='+page+'&f='+f+'&locale='+myAmaz.store;
		if(myAmaz.store == "jp") qString += '&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A';
	} else {
		alert("Error");
		nextBtn.setAttribute('disabled','true');
		page = 1;
		return;
	}
	
	//Connect to Amazon
	connection(qString);
}

function printDoc() {
	if(typeof myAmaz == 'undefined') {
		alert('No document to print');
		return false;
	}else{
		window.open("print.xul", "MAB - Print", "chrome,centerscreen,resizable")
	}	
}

function showDetail(idx) {
	if(idx == -1 || typeof idx == 'undefined') {
		var idx = guiMainTree.currentIndex;
	}
	if(idx == -1) return;
	//I can't find a simple method to get an attribute from a selected row.
	var theRows = guiListTree.getElementsByTagName('treerow');
	var amazPK = theRows[idx].getAttribute('id');
	for(var i=0;i < detRef.length; i++) {
		var content = myAmaz.getDetail(amazPK,detRef[i],true);
		guiDetRef[i].setAttribute('value',content);
	}
	
	//Image
	guiImageSmall.setAttribute('src',myAmaz.getDetail(amazPK,'ImageUrlMedium',false));
		
	//Product Info
		var allInfo = myAmaz.getAllInfo(amazPK);
	printDebug("Enter in getAllInfo:" + allInfo);
	
	//Move ScrollBar at the top
	window.frames[0].scrollTo(0,0);
	
	if(allInfo) {
		commentBtn.setAttribute('disabled','true');
		guiTheInfo.innerHTML = allInfo;
	} else {
		commentBtn.setAttribute('disabled','false');
	}
	
	window.frames[1].scrollTo(0,0);
	//Comments
	var comments = myAmaz.getReviews(amazPK);
	if(comments) {
		commentBtn.setAttribute('disabled','true');
		var header = '<strong>Customer Reviews:</strong><br>';
		guiTheComment.innerHTML = header + comments;
	}else{
		clearComment();
		commentBtn.setAttribute('disabled','false');
	}
}

function getComment() {
	var idx = guiMainTree.currentIndex;
	if(idx == -1) {
		alert("No row selected");
		return false;
	}
	//I can't find a simple method to get an attribute from a selected row.
	var theRows = guiListTree.getElementsByTagName('treerow');
	var amazPK = theRows[idx].getAttribute('id');
		
	//Call Amazon for getting comments
		var qString = getAWSUrl()+'?t='+ASSID[myAmaz.store]+'&dev-t='+DEVT+'&AsinSearch='+amazPK+'&type=heavy&f='+f+'&locale='+myAmaz.store;
		if(myAmaz.store == "jp") qString += '&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A';
		mySearchType = "comment";
		connection(qString);
	//Reset Focus on item
	setFocusOnList(idx);
}

/*Get the bigger product image*/
function getImageLarge() {
	var idx = guiMainTree.currentIndex;
	if(idx == -1) return false;
	
	//I can't find a simple method to get an attribute from a selected row.
	var theRows = guiListTree.getElementsByTagName('treerow');
	var amazPK = theRows[idx].getAttribute('id');
	
	//get large image name
	var imgLarge = myAmaz.getDetail(amazPK,'ImageUrlLarge',false);
	var title = myAmaz.getDetail(amazPK,'ProductName',false);	
	//Open Win for large image
	if(imgLarge) {
		void(window.open(imgLarge,title,'chrome,centerscreen,resizable'));
	}else{
		return false;
	}
		
}


function search() {
	if(typeof myAmaz == 'undefined') {
		myAmaz = new AmazonResult();
	}
	
	var query = getInput();
	page = 1;
	if(query) {
		var qString = getAWSUrl()+'?t='+ASSID[myAmaz.store]+'&dev-t='+DEVT+'&'+getSearchBy()+'='+escape(query)+'&mode='
		+getProductLine()+'&sort='+getSortType()+'&type='+searchType+'&page='+page+'&f='+f+'&locale='+myAmaz.store;
		//short term fix for japanese search
		if(myAmaz.store == "jp") qString += '&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A';
	} else {
		alert("Please, provide a query!");
		guiFindText.focus();
		return;
	}
	
	//Connect to Amazon
	connection(qString);
}

function goAmazon(idx) {
	if(idx == -1) {
		var proceed = confirm("No rows selected. Go to Amazon HomePage?");
		if(proceed) window.open(AMAZONURL[locale],"Amazon");
	} else {	
		//I can't find a simple method to get an attribute from a selected row.
		var theRows = guiListTree.getElementsByTagName('treerow');
		var amazPK = theRows[idx].getAttribute('id');
		var AmazonUrl = myAmaz.getAmazonUrl(amazPK);
		if(AmazonUrl) window.open(AmazonUrl,"Amazon");
		
	}
}

//Search on Google by ProductName
function goGoogle(idx) {
	if(idx == -1) {
		var proceed = confirm("No rows selected. Go to Google HomePage?");
		if(proceed) window.open(GOOGLEURL[locale],"Google");
	} else {	
		var theRows = guiListTree.getElementsByTagName('treerow');
		var amazPK = theRows[idx].getAttribute('id');
		var searchString = myAmaz.getDetail(amazPK,"ProductName",true);
		if(searchString) {
			var words = searchString.split(" ");
			//Google limit to 10 words
			if(words.length > 10) {
				searchString = "";
				for(var i=0;i<10;i++){
					searchString +=words[i]+' ';
				}
			}
			searchString = escape('"'+searchString+'"');
			var googleUrl = GOOGLEURL[locale] + '/search?q=' + searchString + ' -site:'+ AMAZONURL[locale];
			window.open(googleUrl,"Google")
		}
		
	}
}


function wordCount(str) {
	var wc = str.split(" ").lenght;
}

/* Use XMLHttpRequest to make a connection*/
function connection(qString) {
	/*Create the Object*/
	try {
		var req = new XMLHttpRequest();
		req.overrideMimeType("text/xml");
	}catch (e){
		alert('Error creating the connection!');
		if(debugMode) printDebug(e);
		return;
	}
	
	printDebug("Target Url: "+qString);
				
	try {
		//Set Permission only in case of direct connection
		if(aProxy == false) {
			netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
		}
		
		req.open("GET",qString,true);
		req.send(null);
		setMeter('start');
	
	}catch (e){
		alert('An error has occured calling Amazon: '+e);
		printDebug(e);
		return;
	}
	
	//TimeOut
	var iter = timeOut;
	var loaded = false;
	
	var checkLoad = function () {
		if(loaded) {
			clearInterval(intervalID);
		} else if(iter == 0) {
			reqAbort();
			alert('Connection has timed out. Aborted after '+ timeOut + ' seconds');
		} else {
			iter--;
		}
	};
	
	var intervalID =  setInterval(checkLoad,1000);
	
	//Listener to abort the search
	window.addEventListener('keypress',stopConnection,true);
	abortIcon.setAttribute("disabled","false");
	
	function stopConnection(e) {
		if(e.keyCode == 27 && req) {
			reqAbort();
		}
	}
	
	function reqAbort() {
		if(req) req.abort();
		clearInterval(intervalID);
		setMeter('stop');
		document.removeEventListener('keypress',stopConnection,true);
		abortIcon.setAttribute("disabled","true");
	}
	
	req.onload = function() {
		switch(req.readyState) {
			case 1,2,3:
			break;
			case 4:
				loaded = true;
				setMeter('stop');
				if(req.status !=200) {
					alert('The server respond with a bad status code: '+req.status);
					document.removeEventListener('keypress',stopConnection,true);
					abortIcon.setAttribute("disabled","true");
					printDebug("Status Code:"+req.status + '\n Response Text:'+req.responseText);
				} else {
					printDebug("Status Code:"+req.status + '\n Response Text:'+req.responseText);
					document.removeEventListener('keypress',stopConnection,true);
					abortIcon.setAttribute("disabled","true");
					//Work around for Moz 1.3+
					var responseXML = new DOMParser().parseFromString(req.responseText, 'text/xml');
					myAmaz.parseResponse(responseXML);
					//myAmaz.parseResponse(req.responseXML);
				}
			break;
		};
	}
}