//////////////////////////////////////////////
// Search Object VERSION_0.8.5
//////////////////////////////////////////////
//
// Ali Russell 01.2007
//
//////////////////////////////////////////////

//FORM FIELD TYPES
window.SearchFieldType_Text = 0;
window.SearchFieldType_Binary = 0;
window.SearchFieldType_Date = 0;
//###############################


var Search = Class.create();
Search.prototype = {
//
// Member Variables
//array of the advanced search fields
advancedFields: new Array(),

//auto complete field currently
//in focus
autoComplete: null,

//the auto complete div
autoCompleteDiv: null,

//The surface id
advSId: "",

isopen: false,

// Toggle whether to use AutoComplete or not
useAutocomplete: false,

isLoaded: false,

// Flag to test whether to show the complex query warning to users
complexQueryCheck: true,



//
// Constructor
initialize: function(gsBox, gsSBtn, gsCBtn, advSId)
	{
		window.AdvancedSearch = this;
		
		//get the general search elements
		this.gsBox = $(gsBox);
		this.gsSBtn = $(gsSBtn);
		this.gsCBtn = $(gsCBtn);
		
		this.advSId = advSId;
		if (advSId!="")
		{
			//If the advanced search is available then build the main advanced search control
			document.body.appendChild(Builder.node('div', {id: "ASAC", style: "display: none"}, [Builder.node('a', {id: "ASACNoM"}, ["No Matches!"]), Builder.node('a', {id: "ASACLdng"},[Builder.node('img', {src: "./pics/Search/loading.gif", height: "25px"})])]));
			
	
			//create the closed col btn
			this.asCBtn = Builder.node('a', { className: "closeBtn", title: 'Click to close the Advanced Search Panel' }, 
																				[
																				 Builder.node('img', {src: './pics/ColumnBrowser/ClosedColumns/close_btn.png', border: '0'}, [])
																				]);
			
			this.asLoadingNode = Builder.node('div', {}, "Loading Columns...");
			Event.observe(this.asCBtn, "click", this.CloseAS.bindAsEventListener(this));
			
			this.asCont = Builder.node('div', {className: "container"}, 
						 								[
														 	Builder.node('div', {className: "title"},
																		 							[
																									 	Builder.node('div', {className: "titleText"}, ["Advanced Search"]),
																										this.asCBtn
																									]
																		 							),
															this.asLoadingNode
														]
						 								);
			
			this.asDiv = $(Builder.node('div', {id: "AdvSch", style: "display: none"}, [this.asCont]));
			$(advSId).appendChild(this.asDiv);			
			
			document.observe('AdvancedSearch:Open',				this.OpenAS.bindAsEventListener(this));
			
			Event.observe(document.body, "click", this.HideAutoComplete.bindAsEventListener(this));
		}
		
		
		
		
		
		
		//register dom events
		if(this.gsSBtn != null) {Event.observe(this.gsSBtn, "click", this.CheckAS.bindAsEventListener(this)); }
		if(this.gsCBtn != null) {Event.observe(this.gsCBtn, "click", this.ClearAS.bindAsEventListener(this)); }
		Event.observe(this.gsBox, "keyup", this.GSKeyUp.bindAsEventListener(this));			
	
		//subscribe to mspace events
		document.observe('ColumnBrowser:ColumnsLoaded',				this.LoadAdvancedSearch.bindAsEventListener(this));
		
		document.observe('mSpaceHistory:HistoryChange',				this.HistoryChange.bindAsEventListener(this));
		
		document.observe('AdvancedSearch:ClearItem',					this.ClearItem.bindAsEventListener(this));
		document.observe('AdvancedSearch:UpdateItem',					this.UpdateItem.bindAsEventListener(this));		
	},
	
//function to sort the array of columns
//used by the array.sort method
SortCols: function(a, b)
	{
		if (!a.so && b.so)
		{
			return 1;
		}
		if (a.so && !b.so)
		{
			return -1;
		}		
		else if (a.so<b.so)
		{
			return -1;
		}
		else if (a.so>b.so)
		{
			return 1;
		}	
		else
		{
			return 0;
		}		
	},

//Load the advanced search from the
//passed columns object
LoadAdvancedSearch: function(e)
	{
		// Only load the columns once
		if(this.isLoaded)
			return;
			
		var pcols = e.memo;
		
		// Remove Advanced Search Element from the DOM for processing
		this.asDiv.remove();
		
		var thisObj = this;
		var columns = new Array();
		for (var x=0; x<pcols.length; x++) 
		{
			columns.push(pcols[x]);
		}
		
		//sort the columns array
		columns.sort(function(a, b) { return thisObj.SortCols(a, b); });
		
		this.asCont.removeChild(this.asLoadingNode);
		
		this.as_AllFormField = Builder.node('input', {type: "text"});
		Event.observe(this.as_AllFormField, "keyup", this.AnyInputKeyUp.bindAsEventListener(this));
		
		this.advancedFields.push({name:'q', type: 'normal', input: this.as_AllFormField});
		
		//Create an all fields search box
		this.asCont.appendChild(
								Builder.node('div', {className: "AsItem"},
																				[
																					Builder.node('div', {className: "label"},["All"]),
																					this.as_AllFormField
																				]
											 )
								);
		
		this.asCont.appendChild(Builder.node('div', {className: "ASBreak"}));
		
		//loop through the fields adding a new input box for each field
		for (var i=0; i<columns.length; i++)
		{			
			if ((columns[i].ctp==0) || (columns[i].ctp==2))
			{
				//add the field to the advanced fields array
				var tempFF = Builder.node('input', {type: "text"});
				Event.observe(tempFF, "keyup", this.AnyInputKeyUp.bindAsEventListener(this));
				this.advancedFields.push({name:columns[i].uri, type: 'normal', input: tempFF});
					
				//create containing div, and add to the advanced search container
				this.asCont.appendChild(
										Builder.node('div', {className: "AsItem"},
																						[
																							Builder.node('div', {className: "label"},[columns[i].label]),
																							tempFF
																						]
													 )
										);			
			}
		}
		
		
		this.asCont.appendChild(Builder.node('div', {className: "ASBreak"}));
		
		//Add the advanced search buttons.
		this.as_searchBtn = Builder.node('input', {type: "button", value: "Search All"});
		Event.observe(this.as_searchBtn, "click", this.CheckAS.bindAsEventListener(this));
		this.as_searchSomeBtn = Builder.node('input', {type: "button", value: "Search Any"});
		Event.observe(this.as_searchSomeBtn, "click", this.CheckAS.bindAsEventListener(this));	
		this.as_clearBtn = Builder.node('input', {type: "button", value: "Clear"});
		Event.observe(this.as_clearBtn, "click", this.ClearAS.bindAsEventListener(this));
		
		//This is not used any more....
		this.as_incSliceChk = Builder.node('input', {type: "checkbox"});
		
		
		this.asCont.appendChild(
								Builder.node('div', {className: "AsBtns"},
																				[
																					this.as_searchBtn,
																					this.as_searchSomeBtn,
																					this.as_clearBtn/*,
																					Builder.node('label', {}, [this.as_incSliceChk, "Search within slice."])*/																	
																				]
											 )
								);		
		
		if (window.mSpaceHistory.historyHash)
		{
			this.HistoryChange(window.mSpaceHistory.historyHash);
		}
		
		$(this.advSId).update(this.asDiv);
		
		this.isLoaded = true;
	},
	
//open the advanced search form	
OpenAS: function(e)
	{
		if (this.isopen)
			return;
		Effect.BlindDown("AdvSch");
		this.isopen = true;
		
		this.UpdateHistory();
		
	},
	
//close the advanced search form	
CloseAS: function(e)
	{
		if (!this.isopen)
			return;		
		Effect.BlindUp("AdvSch");
		this.isopen = false;
		
		this.UpdateHistory();
	},

//Check to see if the search query is complex or not
CheckAS: function(e, elm)
	{
		//check that the passed element is null, if so find the event element
		var element = elm || Event.element(e);

		var sUrl = window.mSpaceApplication.GetServerUrl("infobox");
		
		var isComplex = false;
		
		//check if the call was from the general search
		if (element==this.gsSBtn)
		{
			var tempgsVal = this.gsBox.value;
			this.ClearAS();
			this.as_AllFormField.value = tempgsVal;
			this.gsBox.value = tempgsVal;
			
			if(this.gsBox.value.indexOf("(") > -1)
				isComplex = true;
		}
		else
		{
			this.gsBox.value = this.as_AllFormField.value;
		}

		//get the search string
		var query = this.GetSearchString(element!=this.gsSBtn);
		
		if(this.complexQueryCheck && (query.complex || isComplex))
		{
			var noBtn = Builder.node('input', {id: 'ComplexQueryNoBtn', value: 'No', type: 'button', onclick: "document.fire('LightBox:Hide')"});
			var yesBtn = Builder.node('input', {id: 'ComplexQueryYesBtn', value: 'Yes', type: 'button'});
			var loading = Builder.node('img', {id: 'ComplexQueryLoading', src: '/pics/InformationControl/Generic/loading_noanim.gif', alt: 'Loading...', style: 'display: none; margin-left: 10px;'});
			
			var dontaskme = Builder.node('div', {style: 'margin-top: 10px;'}, [
																							Builder.node('input', {id: 'ComplexQueryDontAskMe', type: 'checkbox'}),
																							Builder.node('label', {'for': 'ComplexQueryDontAskMe'}, ["Don't ask me again"])
																	]);
			
			Event.observe(yesBtn, "click", this.PerformComplexAS.bindAsEventListener(this));
			
			var complexAlert = Builder.node('div', {className: "ComplexQuery"},
													[
														Builder.node('div', {style: "margin-bottom: 10px;"}, ["It looks like you might be trying to perform a complex query. Please be aware that this may take some time to complete. Are you sure you would like to continue?"]),
														yesBtn,
														noBtn,
														loading,
														dontaskme														
													]
				 );
				 
			document.fire('LightBox:Show', {title: 'Complex Query Warning', childNode:complexAlert});
		}
		else
		{
			this.PerformAS(sUrl+query.url, element);	
		}
	},
	
//Perform an advansed search, 
//called when either buttons are pressed
PerformAS: function(sUrl, element)
	{
		//check if other buttons were pressed, and assign the correct search type
		if (element==this.as_searchBtn)
		{
			sUrl += "&searchtype=and";
		}
		else if (element==this.as_searchSomeBtn)
		{
			sUrl += "&searchtype=or";
		}
		else
		{
			sUrl += "&searchtype=and";
		}
		
		this.UpdateHistory();
		
		//Set the infromation control url
		document.fire('InformationControl:SetUrl', sUrl);
		
		
	},

// User has chosen to do a complex query so perform query request without checking	
PerformComplexAS: function(e, elm)
{
		$('ComplexQueryLoading').style.display = '';
		$('ComplexQueryNoBtn').disabled = true;
		$('ComplexQueryYesBtn').disabled = true;
		$('ComplexQueryDontAskMe').disabled = true;
		
		this.complexQueryCheck = !$('ComplexQueryDontAskMe').checked;
		
		//check that the passed element is null, if so find the event element
		var element = elm || Event.element(e);

		var sUrl = window.mSpaceApplication.GetServerUrl("infobox");
		
		//check if the call was from the general search
		if (element==this.gsSBtn)
		{
			var tempgsVal = this.gsBox.value;
			this.ClearAS();
			this.as_AllFormField.value = tempgsVal;
			this.gsBox.value = tempgsVal;
		}
		else
		{
			this.gsBox.value = this.as_AllFormField.value;
		}

		//get the search string
		var query = this.GetSearchString(element!=this.gsSBtn);
		
		sUrl += query.url;
		
		//check if other buttons were pressed, and assign the correct search type
		if (element==this.as_searchBtn)
		{
			sUrl += "&searchtype=and";
		}
		else if (element==this.as_searchSomeBtn)
		{
			sUrl += "&searchtype=or";
		}
		else
		{
			sUrl += "&searchtype=and";
		}
		
		this.UpdateHistory();
		
		//Set the infromation control url
		document.fire('InformationControl:SetUrl', sUrl);
},

//clear all fields
ClearAS: function(a)
	{
		for (var i=0; i<this.advancedFields.length; i++)
		{
			var fd = this.advancedFields[i];
			fd.input.value = "";			
		}	
		
		this.gsBox.value = "";
		
		document.fire('AdvancedSearch:Clear', null);
	},
	
//clear a particular field
ClearItem: function(e)
	{
		var params = e.memo;
		
		for (var i=0; i<this.advancedFields.length; i++)
		{
			var fd = this.advancedFields[i];
			if (fd.name==params.field)
			{
				fd.input.value = "";			
			}
		}	
		
		
		if (params.type=="and")
		{
			this.PerformAS(null, this.as_searchBtn);
		}
		else
		{
			this.PerformAS(null, this.as_searchSomeBtn);
		}
		
		
	},
	
//update a particular field - used with Spell Check
UpdateItem: function(e)
	{
		var params = e.memo;
		
		for (var i=0; i<this.advancedFields.length; i++)
		{
			var fd = this.advancedFields[i];
			if (fd.name==params.field)
			{
				fd.input.value = params.value;			
			}
		}	
		
		
		if (params.type=="and")
		{
			this.CheckAS(null, this.as_searchBtn);
		}
		else
		{
			this.CheckAS(null, this.as_searchSomeBtn);
		}
		
		
	},
	
UpdateHistory: function()
	{
		var histObj = {};
		if (this.isopen)
			histObj.isopen = "yes";

		//loop trhough all fields, and check if the input
		//has a value, if so, add to the search history
		for (var i=0; i<this.advancedFields.length; i++)
		{
			var fd = this.advancedFields[i];
			if ((fd.name!='q') && (fd.input.value!=""))
			{
				histObj[fd.name] = fd.input.value;
			}
		}	
		
		if ((this.as_AllFormField) && (this.as_AllFormField.value!=""))
		{
			histObj.q = this.as_AllFormField.value;
		}
		
		document.fire('mSpaceHistory:AddHistory', { name: 'Adv.Search', history: Ob2Str(histObj) });		
	},

//reload history search terms
HistoryChange: function(e)
	{
		var hist = null;
		
		if(e)
		{
			if(e.memo)
				hist = e.memo;
			else
				hist = e;
		}
		
		if (hist["Adv.Search"])
		{
			var histObj = {};
			eval("histObj = " + hist["Adv.Search"] + ";");
			
			if (histObj.q)
			{
				this.as_AllFormField.value = histObj.q;
				this.gsBox.value = histObj.q;
			}
			
			for (var i=0; i<this.advancedFields.length; i++)
			{
				var fd = this.advancedFields[i];
				if (fd.name!='q')
				{
					if (histObj[fd.name])
					{
						fd.input.value = histObj[fd.name];
					}
				}
			}	
			
			if (histObj.isopen == "yes")
			{
				this.OpenAS();	
			}
			else
			{
				this.CloseAS();
			}
			
		}
	},
	
//Get the search url string 
//If passed param is true, then return the whole
//advanced search string, not just the general string
GetSearchString: function(adv)
	{

		var searchString = "";
		var isComplex = false;

		if (adv)
		{
			//loop trhough all fields, and check if the input
			//has a value, if so, add to the search url string
			for (var i=0; i<this.advancedFields.length; i++)
			{
				var fd = this.advancedFields[i];
				
				// Does this field contain brackets?
				if(fd.input.value.indexOf("(") > -1)
					isComplex = true;
				
				if ((fd.name!='q') && (fd.input.value!=""))
				{
					searchString += "&scol[]=scol:" + URLEncode(fd.name);
					searchString += "&scol[]=val:" + URLEncode(fd.input.value);
				}
			}	
		}
		
		//If the general input is not empty, add to search
		if ((this.as_AllFormField) && (this.as_AllFormField.value!=""))
		{
			searchString += "&q=" + URLEncode(this.as_AllFormField.value);
		}	
		
		return {complex: isComplex, url: searchString};
	},
	
HandleResponse: function(id, data)
	{
	},
	
GeneralSubmit: function()
	{
	},
	
Clear: function()
	{
	},
	
//perform an advanced seach then the enter button
//is pressed in the general search box
GSKeyUp: function(e, element)
	{
		if (e.keyCode==13)
		{
			this.CheckAS(e, this.gsSBtn);
		}
	},

//called on all search fields, when a key is pressed
AnyInputKeyUp: function(e)
	{
		var element = Event.element(e);
		
		//IF key is enter key, then peform the
		//advanced search
		if (e.keyCode==13)
		{
			this.CheckAS(e, element);
			return;
		}
		
		//IF key is escape key, then clear search
		if ((e.keyCode==27) || (element.value==""))
		{
			element.value = "";
			this.HideAutoComplete(e);
			return;
		}		
		
		//find the field and start auto comlpetion
		if(this.useAutocomplete == true)
		{
			if (element!=this.as_AllFormField)
			{			
				for (var i=0;i<this.advancedFields.length;i++)
				{
					var advsObj = this.advancedFields[i];
					
					if (advsObj.input==element)
					{
						this.PerformAutoCompletion(advsObj);
					}
				}
			}
		}
	},
	
//Clear the current auto completion
ClearASAC: function()
	{
		var ldng = $("ASACLdng").remove();
		var nomt = $("ASACNoM").remove();
		while ($("ASAC").hasChildNodes())
		{
			$("ASAC").firstChild.remove();
		}
		$("ASAC").appendChild(ldng);
		$("ASAC").appendChild(nomt);
		$("ASACLdng").hide();
		$("ASACNoM").hide();
	},
	
//Start a server based auto completion call
PerformAutoCompletion: function(advancedSearchObject)
	{
		
		var inputObj = advancedSearchObject.input;
		
		this.ClearASAC();
		$("ASACLdng").show();
		
		if ((this.autoComplete!=null) && (this.autoComplete == advancedSearchObject))
		{
		}
		else
		{
			this.autoComplete = advancedSearchObject;
			
			$("ASAC").style.top = (findPosY(inputObj) + inputObj.offsetHeight) + "px";
			$("ASAC").style.left = findPosX(inputObj) + "px";
			
			var spacerBorder = 0;
			//Getting the border only works in ie, so this compensates for the lack of 
			//moz-box-typ.? css style
			var styleString = getStyle($("ASAC"), "border");
			if ((styleString!="undefined") && (styleString!=""))
			{
				spacerBorder = parseInt(styleString);
			}					
			
			$("ASAC").style.width = (inputObj.offsetWidth - (spacerBorder*2)) + "px";
			
			$("ASAC").show();
			
			
		}
		
		//auto complete url
		var autoUrl = window.mSpaceApplication.GetServerUrl("autocomplete") + "&column=" + this.autoComplete.name+ "&term=" + inputObj.value + "&limit=10&offset=0";
		
		var thisObj = this;
		
		if (this.ajaxRequest!=null)
			this.ajaxRequest.transport.abort();
		
		//make auto complete ajax request.
		this.ajaxRequest = new Ajax.Request(autoUrl, {
		  requestType: 'get',			  
		  onSuccess: function(transport) 
		  {			
			thisObj.DisplayAutoComplete(eval(transport.responseText));
			thisObj.ajaxRequest = null;
		  },
		  onFailure: function(transport) {
			  alert(transport);
			  thisObj.ajaxRequest = null;
		  }
		});			
	},
	
//Handle the data back from an auto complete
//request
DisplayAutoComplete: function(matches)
	{
		$("ASACLdng").hide();
		if (matches && matches.length>0)
		{	
		
			this.autoMap = {};
			
			//Loop throuh all results and add a mapping
			//for the details of that item.  Also add 
			//an event observation for items when they are clicked.
			for (var i=0;i<matches.length;i++)
			{
				var tempNode = Builder.node('a', {className: "item"});
				tempNode.innerHTML = matches[i].html;
				this.autoMap[tempNode] = matches[i].text;
				Event.observe(tempNode, "click", this.AutoItemClick.bindAsEventListener(this));
				
				$("ASAC").appendChild(tempNode);
				
			}
			
		}
		else
		{
			$("ASACNoM").show();
		}
			
	},
	
//Handle a click on any of the items in the auto complete.
AutoItemClick: function(e)
	{
		var element = Event.element(e);
		
		this.autoComplete.input.value = unescape(this.autoMap[element]);
		
		this.autoComplete = null;
		$("ASAC").hide()
	},
	
//Hide the auto complete div
HideAutoComplete: function(e)
	{
		var element = Event.element(e);
		if (element==$("ASAC"))
			return;
		this.autoComplete = null;
		$("ASAC").hide();
	}


	

}
