/*
 * Copyright 2006 Christian Classics Ethereal Library
 * 
 * This file is part of CCEL-Desktop.
 *
 * CCEL-Desktop is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *   
 * CCEL-Desktop is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with CCEL-Desktop; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * The name of the parameter used to store the query term(s).
 */
var QUERY_PARAM = "qu";

/*
 * A list of all the advanced search fields available for each type of search.
 * This array determines the contents of the dropdown menus.
 */
var fields = new Array();
fields['fulltext'] = new Array("contents","keyword","divTitle","scr","scriptureRef","scriptureCom","scripture","comType","author","title","authorID","bookID");
fields['books'] = new Array("keyword","author","title","ccsubjects","authorID","bookID","lccn","publisher");
fields['definitions'] = new Array("defTerm","type","keyword","author","title","authorID","bookID");
fields['scripture'] = new Array("contents","scr","scriptureRef","scripture","scriptureCom","comType");

//names of the fields to populate the dropdown menus
var fieldNames = new Array();
fieldNames['contents'] = 		'Full text';
fieldNames['keyword'] = 		'Keyword';
fieldNames['divTitle'] = 		'Table of Contents';
fieldNames['scr'] = 			'Scripture';
fieldNames['scripture'] = 		'Scripture Passage';
fieldNames['scriptureCom'] = 	'Scripture Commentary';
fieldNames['scriptureRef'] = 	'Scripture Reference';
fieldNames['comType'] = 		'Commentary Type';
fieldNames['author'] = 			'Author';
fieldNames['title'] = 			'Title';
fieldNames['authorID'] = 		'Author ID';
fieldNames['bookID'] = 			'Book ID';
fieldNames['ccsubjects'] = 		'Subject';
fieldNames['lccn'] = 			'LC Call Number';
fieldNames['publisher'] = 		'Publisher';
fieldNames['defTerm'] = 		'Term';
fieldNames['type'] = 			'Term Type';
fieldNames['score'] = 			'Relevance';

//The example tool-tips that appear onmouseover.
var fieldExampleHelp = new Array();
fieldExampleHelp['contents'] = new Array("Example full text searches:", "God, \"Jesus Christ\", king*");
fieldExampleHelp["keyword"] = new Array("Example keyword searches:", "Augustine, Confessions, calvin, calcom01");
fieldExampleHelp["divTitle"] = new Array("Example table of contents searches:", "index, introduction, chapter");
fieldExampleHelp["scr"] = new Array("Example scripture searches:", "Genesis, Matt. 1, John3.16, Gen.1-2, Deut 6:4-5, Mt 5:1-7:29");
fieldExampleHelp["scripture"] = fieldExampleHelp["scr"];
fieldExampleHelp["scriptureCom"] = fieldExampleHelp["scr"];
fieldExampleHelp["scriptureRef"] = fieldExampleHelp["scr"];
fieldExampleHelp["comType"] = new Array("Example commentary type searches:", "commentary, sermon, hymn, scripture");
fieldExampleHelp["author"] = new Array("Example author searches:", "Augustine, Calvin, Schaff");
fieldExampleHelp["title"] = new Array("Example title searches:", "Bible, Encyclopedia, Uniformity");
fieldExampleHelp["authorID"] = new Array("Example author ID searches:", "augustine, albert, bible");
fieldExampleHelp["bookID"] = new Array("Example book ID searches:", "asv, calcom01, bibledict");
fieldExampleHelp["ccsubjects"] = new Array("Example subject searches:", "hymn, Bible, proofed, classic");
fieldExampleHelp["lccn"] = new Array("Example Libray of Congress searches:", "bv42, bv*, bs491");
fieldExampleHelp["publisher"] = new Array("Example publisher searches:", "London, New York");
fieldExampleHelp["defTerm"] = new Array("Example term searches:", "Aaron, martyrdom, Tarsus");
fieldExampleHelp["type"] = new Array("Example term type searches:", "dictionary, encyclopedia, scripture");

//Tool-tip help on the various fields in the dropdown menu
var fieldSubjectHelp = new Array();
fieldSubjectHelp['contents'] = 'searches the contents of the book';
fieldSubjectHelp['keyword'] = 'searches by author name and ID, as well as book title and ID';
fieldSubjectHelp['divTitle'] = 'searches the section headers in the table of contents';
fieldSubjectHelp['scr'] = 'searches for scripture references, commentaries, and passages';
fieldSubjectHelp['scriptureRef'] = 'searches for documents that refer to a certain passage';
fieldSubjectHelp['scriptureCom'] = 'searches for commentaries on a certain passage';
fieldSubjectHelp['scripture'] = 'searches for Bibles containing a certain passage';
fieldSubjectHelp['comType'] = 'searches for commentaries of a certain type';
fieldSubjectHelp['author'] = 'searches for the author\'s name of the book';
fieldSubjectHelp['title'] = 'searches for the title of the book';
fieldSubjectHelp['authorID'] = 'searches for the unique author identifier';
fieldSubjectHelp['bookID'] = 'searches for the unique book identifier';
fieldSubjectHelp['ccsubjects'] = 'searches for the subject of the book';
fieldSubjectHelp['lccn'] = 'searches for Library of Congress call number';
fieldSubjectHelp['publisher'] = 'searches for the book\'s publisher';
fieldSubjectHelp['defTerm'] = 'searches for encyclopedia and dictionary terms';
fieldSubjectHelp['type'] = 'searches for terms of a particular type';

/*
 * Displays the text of the given argument(s) in div#helpbox.
 *
 * This function may receive zero or more arguments.
 *
 * Each argument will be displayed on its own line of div#helpbox, separated by a <br />.
 * If zero arguments are given, div#helpbox will be blank.
 *
 * Alternatively, rather than passing each line as its own argument, you may also pass
 * one array whose elements contain the contents of each line.
 *
 * Valid Signatures:
 * null showHelp ( string line [, string line [, ...]] )
 * null showHelp ( array lines )
 */
function showHelp(){
	var helpbox = document.getElementById("helpbox");
	if(helpbox){
		while(helpbox.childNodes && helpbox.childNodes.length>0){
			helpbox.removeChild(helpbox.childNodes[0]);
		}
		if (arguments.length == 1 && typeof arguments[0] == 'object' && arguments[0].constructor.toString().indexOf('Array') > -1){
			// If there is exactly one argument, and it's an array, then treat
			// that array as the list of lines to be displayed in the helpbox.
			arguments = arguments[0];
		}
		for (var i = 0; i < arguments.length; i++){
			if(i > 0)
				helpbox.appendChild(document.createElement("br"));
			helpbox.appendChild(document.createTextNode(arguments[i]));
		}
	}
}

/*
 * Changes the current search mode (i.e., the type of search) while keeping everything
 * else on the page the same.
 *
 * This is especially useful for switching tabs.
 */
function changeSearchMode(mode){
	window.location = assembleSearchURL(IS_ADVANCED, mode);
}

/*
 * Switch from basic to advanced search view.
 *
 * As of now, the state remains exactly the same except for advanced search mode
 * is turned on.
 */
function showAdvanced() {
	window.location = assembleSearchURL(true, CATEGORY);
}

/*
 * Switch from advanced to basic search view.
 *
 * As of now, the state remains exactly the same except for advanced search mode
 * is turned off.
 */
function showBasic() {
	window.location = assembleSearchURL(false, CATEGORY);
}

/*
 * Perform an advanced search.
 *
 * Specifically, this means assembling the advanced search textboxes and dropdown
 * menus into a single string (the query)
 */
function doAdvancedSearch() {
	window.location = assembleSearchURL(false, CATEGORY);
 }
 
/*
 * The fundamental function for switching pages.
 *
 * Providing values for all parameters to this function can guarentee the state
 * of the page remains consistent.
 */
function assembleSearchURL(isAdvanced, category) {
	var querystring = '?qu=' + encodeURI(getQu()) + '&category=' + encodeURI(category);
	var order = getOrder();
	if (order.length > 0)
		querystring += '&order=' + encodeURI(order);
	if (isAdvanced)
		querystring += '&advanced';
	return getBaseURL() + querystring;
}

/*
 * Returns everything before the question mark in the current URL.
 *
 * In other words, returns everything up to the querystring.
 */
function getBaseURL() {
	var url = document.location.href;
	var questionPos = url.indexOf("?");
	if (questionPos > -1)
		url = url.substr(0, questionPos);
	return url;
}

/*
 * Returns the current query.
 *
 * If we're currently in advanced view, the current query is determined by assembling
 * the advanced search text boxes and dropdown menues into a single string.
 *
 * Otherwise, we're in basic view, in which case the current query is simply the
 * content of div#search_basicBox.
 */
function getQu() {
	if (IS_ADVANCED) {
		return getFullSearchString();
	}
	else {
		var box = document.getElementById("search_basicBox");
		if (box)
			return box.value;
		else
			return "";
	}
}

/*
 * Returns a string representing the desired means of ordering the results.
 *
 * If we're currently on the advanced search page (i.e., if select#order exists),
 * then the desired order is determined by the currently selected index of the
 * select#order dropdown menu.
 *
 * Otherwise, the order is determined by the ORDER constant.
 */
function getOrder() {
	if (IS_ADVANCED && document.getElementById && document.getElementById("order")) {
		var order = document.getElementById("order");
		return order.options[order.selectedIndex].value;
	}
	return ORDER;
}

/*
 * Assembles the pieces of the advanced search into a single query in such a way
 * that it's reversable (i.e., parsable).
 *
 * Uses getSearchString() to assemble the keyword(s) of a given row.
 */
function getFullSearchString(){
//	alert("In getFullSearchString()");
 	var searchString = "";
	var i=1;
 	while (document.getElementById('q'+i)) {
 		var searchS = getSearchString(i);
 		if(searchS.length>0){
 			var boolValue="";
 			var bool = document.getElementById('bool'+i);
 			if(bool && bool.selectedIndex>=0)
 				boolValue = bool.options[bool.selectedIndex].value;
 			if(searchString.length>0 || boolValue=="NOT"){
	 			searchString+= boolValue+" ";
	 			if(searchS.indexOf(':')==-1 && boolValue!="AND")
	 				searchString+= "("+searchS+") ";
	 			else
	 				searchString+= searchS + " ";
	 		}else
	 			searchString+= searchS + " ";
 		}
		i++;
 	}
 	var form = document.forms['searchFields'];
 	if(form.languageID && form.languageID.options.selectedIndex>0)
 		searchString+=" languageID:"+form.languageID.
 			options[form.languageID.options.selectedIndex].value;
 	if(CATEGORY == 'books'){
	 	if(form.edition && form.edition.options.selectedIndex>0)
	 		searchString+=" edition:"+form.edition.
	 			options[form.edition.options.selectedIndex].value;
	 	if(form.publication && form.publication.value){
	 		var pub = form.publication.value;
	 		pub = pub.split(/\s*[\-\_\=]+\s*/);
	 		searchString+=" publication:["+pub[0]+" TO "+pub[1]+"]";
	 	}
 	}
 		
 	//alert(searchString);
 	return searchString;
}

/*
 * Helper function for getFullSearchString().
 *
 * Assembles together the keyword (q), and field
 * name (type) fields for a given row (the formNum argument).
 */
function getSearchString(formNum){
//	alert("In getSearchString(" + formNum + ")");
 	var type=document.getElementById('type'+formNum);
 	var q=document.getElementById('q'+formNum);
 	var field = type.options[type.selectedIndex].value;
	if(q.value.length>0){
	 	if(field.indexOf("scr")!=-1)
	 		return field+ ':"' +q.value.replace(/"/g,'')+ '"';
		if(field == fields[CATEGORY][0])
			return q.value;
		else if(q.value.indexOf(' ')==-1
				|| (q.value.charAt(0)=='[' && q.value.charAt(q.value.length-1)==']')
				|| (q.value.charAt(0)=='{' && q.value.charAt(q.value.length-1)=='}')
				|| (q.value.charAt(0)=='(' && q.value.charAt(q.value.length-1)==')'))
			return field+":"+q.value;
		else
 			return field+":("+q.value+")";
 	}
 	return "";
}

/*
 * Dynamically updates the advanced search page with the number of results for
 * the given row (formNum).
 *
 * This function first queries the server requesting the number of results and
 * then uses setNumText() to display that number to the user.
 */
function getNum(formNum){
	//alert("In getNum("+formNum+")");
	var searchString = getSearchString(formNum);
	if(!searchString || searchString.length<1){
		setNumText(formNum,"? hits","");
		return false;
	}
	var url = "/search?category=" + CATEGORY + "&numHits&" + QUERY_PARAM + "=" + encodeURI(searchString);
	//alert(url);
	setNumText(formNum,"Searching",url);
	var xmlhttp;
	if (window.XMLHttpRequest){ // code for Mozilla, etc.
		xmlhttp=new XMLHttpRequest();
	}else if (window.ActiveXObject){ // code for IE
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP")
	}
	xmlhttp.open("GET",url,true);
	xmlhttp.onreadystatechange=
		function(){
			if (xmlhttp.readyState==4){ // if xmlhttp shows "loaded"
				var text = xmlhttp.responseText;
				var startText = '<span id="ccelNumHits">';
				var index = text.indexOf(startText);
				if(index==-1)
					setNumText(formNum,"Error","");
				else{
					text = text.substring(index+startText.length);
					index = text.indexOf('</span>');
					text = text.substring(0,index);
					setNumText(formNum,text,url);
				}
				xmlhttp=null;
			}
		}
	xmlhttp.send(null);
 	return false;
 }
 
 /*
  * Helper function for getNum().
  *
  * Sets the contents of the "tooltip" text for the given row (specified by formNum)
  * to the given text (specified by result). Also, the text is hyperlinked to the given
  * URL, if one is provided.
  */
 function setNumText(formNum, result, url){
	var type = document.getElementById('type'+formNum);
	type.style.marginRight = ".5em";
	var td = type.parentNode;
	while(type.nextSibling)
		td.removeChild(type.nextSibling);
	var text = document.createTextNode("("+result+")");
	var wrap = document.createElement("i");
	wrap.style.whiteSpace = "nowrap";
	wrap.style.fontSize="80%";
	wrap.onmouseout=function(){showHelp('');}
	wrap.appendChild(text);
	if(url.length>1){
		url = url.replace("&numHits","");
		text = document.createElement("a");
		wrap.onmouseover=function(){
			showHelp('Click to view the search results for this row of the query');
		}
		text.href = url;
		text.appendChild(wrap);
		wrap=text;
	}
	td.appendChild(wrap);
}

/*
 * Updates the given row based on changes the user may have made.
 */
 function updateField(rowNum){
 	var type = document.getElementById('type'+rowNum);
 	var q = document.getElementById('q'+rowNum);
 	if(type){
		var field=type.options[type.selectedIndex].value;
		q.onmouseover=function(){
			showHelp(fieldExampleHelp[field]);
		}
	}
 }
//populates the fields available for searching for the index and search mode
function populateFieldTypes(category, formNum, selected){
	var selectBox = document.getElementById("type"+formNum);
	selectBox.options.length = 0;
	var fieldArray = fields[category];
	for(var i=0; i<fieldArray.length; i++) {
		selectBox[i] = new Option(fieldNames[fieldArray[i]], fieldArray[i]);
		selectBox[i].onmousemove = function(){
				showHelp('Select the search field for this part of the query.',
 					fieldNames[this.value]+": "+fieldSubjectHelp[this.value]);
			};
		selectBox[i].onmouseout = function(){
				showHelp('');
			};
	}
	if(selected.length > 0)
		selectBox.value = selected;
	else
		selectBox.selectedIndex = (formNum-1) % fieldArray.length;
}

// select an English translation if contextual search is chosen
function contextSelected() {
	var combo = document.getElementById("translation");
	if(combo.selectedIndex < 1 || combo.selectedIndex > numContextTranslations)
		combo.selectedIndex = 1;
}

// select text-only search if a non-English translation is chosen
function translationChange() {
	var button = document.getElementById("textButton");
	var combo = document.getElementById("translation");
	if(combo.selectedIndex < 1 || combo.selectedIndex > numContextTranslations)
		button.checked = true;
}
