
	/**
	 * Custom GOOGLE API search component
	 * @param SearchEngingeId the custom google searchengine ID
	 * @param HTMLContainer the HTML element that will hold the search component
	 *
	 * @author Zaïd Sadhoe <zaid@ooip.nl>
	 */

	var customGoogleSearch = function(SearchEngineId, HTMLContainer, HTMLContainerClear)
	{
		/**
		 * PUBLIC PROPERTIES
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		this.resetFiltersOnSearch	= true;									// clear the selected filters on every new search
		this.focusOnStart			= true;									// start with focus on the searchfield
		this.searchText				= 'Zoeken in het palliatieve domein';	// the default text visible in the searchfield when not focused
		this.submitText				= 'Zoeken';								// the text on the searchbutton

		/**
		 * PUBLIC VARIABES
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		this.id = SearchEngineId;

		/**
		 * PRIVATE VARIABES
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		var self			= this;
		var searchControl	= null;
		
		var location = '';

		var HTMLHolder, HTMLTop, HTMLContent, HTMLHidden;
		var HTMLLabels, HTMLSearch, HTMLForm, HTMLInput, HTMLSubmit, HTMLSubmitText;
		var HTMLTable, HTMLRow, HTMLFilters, HTMLResults;

		var searchKey	= '';
		var searchFocus = false;
		var isSearching = false;
		var isStarted	= false;

		var labelKeys	= [];
		var labels		= [];
		var labelMap	= {};

		var hasFilters  = false;
		var filterKeys	= {};
		var filterParts	= {};
		var filters		=
		{
			'filetype' :
			{
				title : 'Type resultaat',
				items :
				[
					['' 	, 'Elke type'],
					['html'	, 'Webpagina'],
					['doc'	, 'Word document'],
					['pdf'	, 'Adobe PDF']
				]
			},
			'daterange' :
			{
				title : 'Gewijzigd op',
				items :
				[
					['' 	, 'Elke periode'],
					['d' 	, 'Afgelopen 24 uur'],
					['w' 	, 'Afgelopen week'],
					['m' 	, 'Afgelopen maand'],
					['6m'	, 'Afgelopen zes maanden'],
					['y'	, 'Afgelopen jaar']
				]
			}
		}

		/**
		 * Load the google search and set callback
		 *
		 * @param the array of arguments passed to the class
		 * @return void
		 * @see customGoogleSearch.create
		 * @author Zaïd Sadhoe
		 */

		function construct(arguments)
		{
			google.load('search', '1');
			google.setOnLoadCallback
			(
				function()
				{
					setupElements();
					
					// Toegevoegd 23-01 
					var customSearchOptions = {};
					var googleAnalyticsOptions = {};
					googleAnalyticsOptions['queryParameter'] = 'q';
					googleAnalyticsOptions['categoryParameter'] = '';
					customSearchOptions['googleAnalyticsOptions'] = googleAnalyticsOptions;

					
					//searchControl = new google.search.CustomSearchControl(self.id);
					searchControl = new google.search.CustomSearchControl(self.id, customSearchOptions);
					searchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);

					var drawOptions = new google.search.DrawOptions();
						drawOptions.setDrawMode(google.search.SearchControl.DRAW_MODE_TABBED);
						drawOptions.setSearchFormRoot(HTMLHidden);

					searchControl.setSearchCompleteCallback(self, onSearchComplete);
					searchControl.setSearchStartingCallback(self, onSearchStart);
					
					searchControl.draw(HTMLResults, drawOptions);

					detectParams();

					isStarted = true;
				}
				, true
			);
		};

		/**
		 * Starts the execution of the search of the searchcontrol
		 *
		 * @param focus boolean wheter or not to take focus
		 * @author Zaïd Sadhoe
		 */

		this.search = function(Keyword)
		{
			searchKey = typeof(Keyword) == 'undefined' ? searchKey : Keyword;

			this.setSearchFocus(true);

			if(searchKey)
			{
				try{ searchControl.execute(searchKey); } catch(e){ }
			}
			else if(getSearchQuery())
			{
				try{ searchControl.execute(getSearchQuery()); } catch(e){ }
			}
			else
			{
				this.clear();
			}
		};

		/**
		 * clear all search results
		 *
		 * @param focus boolean wheter or not to take focus
		 * @author Zaïd Sadhoe
		 */

		this.clear = function()
		{
			searchControl.clearAllResults();

			HTMLLabels.style.display	= 'none';
			HTMLFilters.style.display	= 'none';

			if(HTMLContainerClear)
			{
				dom.getById(HTMLContainerClear).style.display = '';
			}
			
			if(!isStarted)
			{
				this.setSearchFocus(this.focusOnStart);
			}
			
			setParams();
		}

		/**
		 * Adds labels for the restriction search
		 *
		 * @param Key the key value, the real value to search for
		 * @param Title the title value, the value displayed
		 * @return void
		 * @author Zaïd Sadhoe
		 */

		this.addLabel = function(Key, Title)
		{
			labels.push([Key, Title]);
		};

		/**
		 * select a label
		 *
		 * @param multiple parameters possible
		 * @return void
		 * @author Zaïd Sadhoe
		 */

		this.selectLabel = function()
		{
			labelKeys = typeof(arguments[0]) == 'object' ? arguments[0] : arguments;

			for(var a in labelMap)
			{
				labelMap[a].className = 'ooip-label';
			}

			(HTMLLabels && labelKeys.length == 1 && typeof(labelKeys[0]) == 'string' && typeof(labelMap[labelKeys[0]]) != 'undefined' ? (labelMap[labelKeys[0]].className = 'ooip-label ooip-label-selected') : null);
		};

		/**
		 * remove all filters
		 *
		 * @return void
		 * @author Zaïd Sadhoe
		 */

		this.clearFilters = function()
		{
			filters = {};
		};

		/**
		 * Adds filters for the filtered search
		 *
		 * @param Key the key value, the real value to search for
		 * @param Title the title value, the value displayed
		 * @return void
		 * @author Zaïd Sadhoe
		 */

		this.addFilter = function(Key, Title)
		{
			filters[Key] = { title : Title, items : []};
		};

		/**
		 * Adds filters for the filtered search
		 *
		 * @param Key the key of the filter
		 * @param Value the key value, the real value to search for
		 * @param Title the title value, the value displayed
		 * @return void
		 * @author Zaïd Sadhoe
		 */

		this.addFilterItem = function(Key, Value, Title)
		{
			filters[Key].items.push([Value, Title]);
		};

		/**
		 * select a filter
		 *
		 * @param Key the key of the filter
		 * @param Value the key value, the real value to search for
		 * @return void
		 * @author Zaïd Sadhoe
		 */

		this.selectFilter = function(Key, Value)
		{
			filterKeys[Key] = Value;

			if(typeof(filterParts[Key]) != 'undefined')
			{
				for(var a in filterParts[Key])
				{
					var item				= filterParts[Key][a];
						item[0].className	= item[1] == Value ? 'ooip-filter-item ooip-filter-item-selected' : 'ooip-filter-item';
				}
			}
		};

		/**
		 * reset all selected filters
		 *
		 * @param Key the key of the filter
		 * @param Value the key value, the real value to search for
		 * @return void
		 * @author Zaïd Sadhoe
		 */

		this.resetFilters = function(K)
		{
			for(var a in filterKeys)
			{
				this.selectFilter(a, '');
			}
		};

		/**
		 * Set focus on the searchfield
		 *
		 * @param focus boolean wheter or not to take focus
		 * @author Zaïd Sadhoe
		 */

		this.setSearchFocus = function(Focus)
		{
			searchFocus = typeof(Focus) != 'undefined' ? Focus : searchFocus;
			searchKey	= HTMLInput.value != this.searchText && HTMLInput.value && !searchFocus ? HTMLInput.value : searchKey;

			var newValue = searchKey || searchFocus ? searchKey : this.searchText;

			if(newValue != HTMLInput.value)
			{
				HTMLInput.value = searchKey || searchFocus ? searchKey : this.searchText;
			}

			HTMLInput.className	= searchKey || searchFocus ? 'ooip-input' : 'ooip-input ooip-input-empty';

			(searchFocus ? HTMLInput.focus() : HTMLInput.blur());
		};

		/**
		 * creates custom google query parameters
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function getSearchQuery()
		{
			var query = '';

			for(var a = 0; a < labelKeys.length; a++)
			{
				if(labelKeys[a])
				{
					query += 'more:' + labelKeys[a] + ' ';
				}
			}

			for(var b in filterKeys)
			{
				if(filterKeys[b])
				{
					if(b == 'filetype')
					{
						query += getSearchQueryFiletype(b, filterKeys[b]);
					}
					else if(b == 'daterange')
					{
						query += getSearchQueryDaterange(b, filterKeys[b]);
					}
					else
					{
						query += b + ':' + filterKeys[b] + ' ';
					}
				}
			}

			return query.substr(0, query.length -1 );
		};

		/**
		 * creates custom google query parameters for filetype
		 *
		 * @param Key the filter key
		 * @param Value the filter value
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function getSearchQueryFiletype(Key, Value)
		{
			var query = '';

			switch(Value)
			{
				case 'html':
				
					query = '-filetype:pdf -filetype:doc -filetype:xls -filetype:ppt -filetype:swf -filetype:xml -filetype:rtf -filetype:txt ';
					break;

				default:
				
					query = 'filetype:'+Value+' ';
					break;
			}
			
			return query;
		}

		/**
		 * creates custom google query parameters for daterange
		 *
		 * @param Key the filter key
		 * @param Value the filter value
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function getSearchQueryDaterange(Key, Value)
		{
			var startDate	= null;
			var endDate		= new Date();

			var query = '';

			switch(Value)
			{
				case 'd':
				
					startDate = new Date(endDate.getTime() - (1000 * 60 * 60 * 24));
					break;

				case 'w':
				
					startDate = new Date(endDate.getTime() - (1000 * 60 * 60 * 24 * 7));
					break;

				case 'm':
				
					startDate = new Date(endDate.getTime() - (1000 * 60 * 60 * 24 * 30));
					break;

				case '6m':
				
					startDate = new Date(endDate.getTime() - (1000 * 60 * 60 * 24 * 183));
					break;

				case 'y':

					startDate = new Date(endDate.getTime() - (1000 * 60 * 60 * 24 * 365));
					break;
			}
			
			if(startDate)
			{
				query = 'daterange:' + startDate.getJulian() + '-'  + endDate.getJulian() + ' ';
			}

			return query;
		}

		/**
		 * detect the parameters in the location
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function detectParams()
		{
			if(location != window.location.href && !isSearching)
			{
				//alert('changed');
				
				var values = {};

				location = window.location.href.toString();
				
				var params = location.match(/(\#)([^\#\?]+)$/i);

				if(params)
				{
					var parts = params[2].match(/[^\&]+\=[^\&]+/ig);
					
					if(parts)
					{
						for(var a = 0; a < parts.length; a++)
						{
							var key = parts[a].match(/([^\&]+)\=([^\&]+)/i);
							
							values[unescape(key[1])] = unescape(key[2]);
						}
					}
				}

				self.selectLabel((typeof(values.label) != 'undefined' ? values.label : ''));

				for(var c in filterKeys)
				{
					self.selectFilter(c, (typeof(values[c]) != 'undefined' ? values[c] : ''));
				}
				
				self.search((typeof(values.q) != 'undefined' ? values.q : ''));
			}
			
			setTimeout(detectParams, 1000);
		}

		/**
		 * set the parameters in the location
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function setParams()
		{
			var locationString = location.replace(/(\#)([^\#\?]+)$/i, '');
			
			locationPart  = (searchKey ? 'q=' + escape(searchKey) : '');
			locationPart += (labelKeys.length && labelKeys[0]? '&label=' + escape(labelKeys[0]) : '');

			for(var b in filterKeys)
			{
				locationPart += (filterKeys[b] ? '&' + b + '=' + filterKeys[b] : '');
			}
			
			var newLocation = locationString + (locationPart ? '#' + locationPart : '');
			
			if(newLocation != location)
			{
				location = newLocation;

				window.open(location, '_self');
			}
		}

		/**
		 * Event before search starts
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		var onSearchStart = function(SearchControl, Searcher, Query)
		{
			isSearching = true;

			Searcher.setRestriction(google.search.Search.RESTRICT_EXTENDED_ARGS, { 'filter' : '0'});
			Searcher.setQueryAddition(searchKey ? getSearchQuery() : '');
		};

		/**
		 * Event after search ends
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		var onSearchComplete = function(SearchControl, Searcher)
		{
			setParams();

			isSearching = false;
			//alert(Searcher.cursor.estimatedResultCount);
			//SearchControl.clearAllResults();
			//MB uitgezet, anders wordt filter deel verborgen
			//HTMLFilters.style.display	= hasFilters ? '' : 'none';
			HTMLFilters.style.display	=  '';
			HTMLLabels.style.display	= labels.length ? '' : 'none';
			
			if(HTMLContainerClear)
			{
				dom.getById(HTMLContainerClear).style.display = 'none';
			}
		};

		/**
		 * Handles the search input field events
		 *
		 * @param e event object
		 * @private
		 * @author Zaïd Sadhoe
		 */

		var onSearchInputEvent = function(event)
		{
			switch(event.type)
			{
				case 'blur':
				case 'focus':

					self.setSearchFocus( event.type == 'focus');
					break;
					
				default:

					searchKey = HTMLInput.value;
					break;
			}

			return true;
		};

		/**
		 * Handles the search controls when submit is pressed
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		var onSearchInputSubmit = function()
		{
			if(self.resetFiltersOnSearch)
			{
				self.resetFilters();
			}

			self.search();
			return false;
		};

		/**
		 * Handles the search controls when submit is pressed
		 *
		 * @param Key the filter key
		 * @param Value the filter value
		 * @private
		 * @author Zaïd Sadhoe
		 */

		var onFilterSelect = function(Key, Value)
		{
			self.selectFilter(Key, Value);
			self.search();
		};

		/**
		 * Handles the search controls when label is pressed
		 *
		 * @param Key the label key
		 * @param Value the label value
		 * @private
		 * @author Zaïd Sadhoe
		 */

		var onLabelSelect = function(Key)
		{
			switch(Key)
			{
				case 'internet':

					searchKey	= HTMLInput.value != this.searchText && HTMLInput.value && !searchFocus ? HTMLInput.value : searchKey;
					var newWindow = window.open('http://www.google.nl/#q=' + searchKey , '_blank');
					newWindow.focus();
					break;

				default:

					self.selectLabel(Key);
					self.search();
					break;
			}
		};

		/**
		 * creates the HTML elements for the custom search
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function setupElements()
		{
			HTMLHolder	= dom.append(HTMLContainer	, dom.create('div', null, { 'class' : 'cse-ooip' }));
			HTMLHidden	= dom.append(HTMLHolder		, dom.create('div', null, null, { 'display' : 'none' }));
			HTMLTop		= dom.append(HTMLHolder		, dom.create('div', null, { 'class' : 'ooip-control' }));
			HTMLContent	= dom.append(HTMLHolder		, dom.create('div', null, { 'class' : 'ooip-content' }));

			//create search elements
			HTMLSearch 			= dom.append(HTMLTop	, dom.create('span', null, { 'class' : 'ooip-search' }));
			HTMLForm 			= dom.append(HTMLTop	, dom.create('form', null, { 'display' : 'none' }));
			HTMLInput			= dom.append(HTMLSearch	, dom.create('input', null, { 'class' : 'ooip-input', 'type' : 'text', 'size' : '50' }));
			HTMLSubmit			= dom.append(HTMLSearch	, dom.create('span', null, { 'class' : 'ooip-submit' }));
			HTMLSubmitText		= dom.append(HTMLSubmit	, dom.create('em', self.submitText, { 'class' : 'ooip-submit' }));

			//create labels elements
			HTMLLabels			= dom.append(HTMLTop	, dom.create('div', null, { 'class' : 'ooip-labels' }));

			//create left elements
			HTMLTable			= dom.append(HTMLContent, dom.create('table', null, { 'class' : 'ooip-content-holder', 'cellpadding' : '0', 'cellspacing' : '0', 'width' : '100%' }));
			HTMLRow				= dom.append(HTMLTable	, dom.create('tr', null));
			HTMLFilters		 	= dom.append(HTMLRow	, dom.create('td', null, { 'class' : 'ooip-filters', 'align' : 'left', 'valign' : 'top' }));
			HTMLResults			= dom.append(HTMLRow	, dom.create('td', null, { 'class' : 'ooip-results', 'align' : 'left', 'valign' : 'top' }));

			setupSearchControls();
			setupLabelControls();
			setupFilterControls();
		};

		/**
		 * sets up the search controls and listens to their events
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function setupSearchControls()
		{
			google.search.CustomSearchControl.attachAutoCompletion(self.id, HTMLInput, HTMLForm);

			var ps = HTMLInput.onpaste;
			var ku = HTMLInput.onkeyup;
			var bl = HTMLInput.onblur;

			HTMLInput.onpaste	= function(e){ onSearchInputEvent(e ? e : event); try{ ps(e); } catch(e){ } };
			HTMLInput.onkeyup	= function(e){ onSearchInputEvent(e ? e : event); try{ ku(e); } catch(e){ } };
			HTMLInput.onblur	= function(e){ onSearchInputEvent(e ? e : event); try{ bl(e); } catch(e){ } };

			HTMLInput.onfocus	= function(e){ onSearchInputEvent(e ? e : event); };
			HTMLInput.onchange	= function(e){ onSearchInputEvent(e ? e : event); };

			HTMLForm.submit 	= function(){ onSearchInputSubmit(); };
			HTMLSubmit.onclick 	= function(){ onSearchInputSubmit(); };

			self.setSearchFocus(self.focusOnStart);
		};

		/**
		 * sets up the label controls
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function setupLabelControls()
		{
			if(labels.length)
			{
				for(var a in labels)
				{
					setupLabelControl(labels[a][0], labels[a][1]);
				}

				self.selectLabel(labelKeys.length ? labelKeys : labels[0][0]);
			}

			HTMLLabels.style.display = 'none';
		};

		/**
		 * sets up one label
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function setupLabelControl(Key, Value)
		{
			var label = dom.append(HTMLLabels, dom.create('a', Value, { 'class' : 'ooip-label' }));

			label.onclick = function(){ onLabelSelect(Key);return false; };
			
			labelMap[Key] = label;
		}

		/**
		 * sets up the filter controls
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function setupFilterControls()
		{
			var holder = dom.append(HTMLFilters, dom.create('img', null, { 'width' : '100', 'src' : '', 'height' : '1' }));
			
			for(var a in filters)
			{
				var holder = dom.append(HTMLFilters, dom.create('ul', null, { 'class' : 'ooip-filter' }));
				var title = dom.append(holder, dom.create('li', filters[a].title, { 'class' : 'ooip-filter-title' }));

				filterParts[a] = [];

				for(var b in filters[a].items)
				{
					setupFilterControl(a, b, holder);

					hasFilters = true;
				}

				self.selectFilter(a, (typeof(filterKeys[a]) != 'undefined' ? filterKeys[a] : filters[a].items[0][0]));
			}

			HTMLFilters.style.display = 'none';
			
		};

		/**
		 * sets up one search control and listens to the events
		 *
		 * @private
		 * @author Zaïd Sadhoe
		 */

		function setupFilterControl(Key, Value, Holder)
		{
			var item = dom.append(Holder, dom.create('li', null, { 'class' : 'ooip-filter-item' }));
			var link = dom.append(item, dom.create('a', filters[Key].items[Value][1], { 'class' : 'ooip-filter-link', 'href' : '#', 'title' : filters[Key].title + ': ' + filters[Key].items[Value][1]}));

			link.onclick = function(){ onFilterSelect(Key, filters[Key].items[Value][0]);return false; };

			filterParts[Key].push([item, filters[Key].items[Value][0]]);
		}

		construct(arguments);
	}

	/**
	 * DOM component - lets you acces, create, append and remove elements
	 * @param SearchEngingeId the custom google searchengine ID
	 * @param HTMLContainer the HTML element that will hold the search component
	 *
	 * @author Zaïd Sadhoe <zaid@ooip.nl>
	 */

	var dom = new function()
	{
		/**
		 * Create an HTML element with the specified text, attributes and styles
		 *
		 * @param Name the tagname of the HTML element
		 * @param Text the text content of the element
		 * @param Attributes an Object with keys and value pairs
		 * @param Styles an Object with keys and value pairs
		 * @return HTMLElement
		 * @author Zaïd Sadhoe
		 */

		this.create = function(Name, Text, Attributes, Styles)
		{
			var node = document.createElement(Name);

			this.setAttributes(node, Attributes);
			this.setStyles(node, Styles);

			if(Text)
			{
				var textNode = document.createTextNode(Text);

				node.appendChild(textNode);
			}

			return node;
		};

		/**
		 * Append an HTML element to another HTML element at the given index
		 *
		 * @param Parent the id or object of the HTML element of the parent
		 * @param Node the HTML element of the child
		 * @param Index and index number at which the element should be appended
		 * @return HTMLElement
		 * @author Zaïd Sadhoe
		 */

		this.append = function(Parent, Node, Index)
		{
			var parent = typeof(Parent) == 'string' ? this.getById(Parent) : Parent;

			if(typeof(Index) == 'number' && Index >= 0 && Index < parent.childNodes.length)
			{
				parent.insertBefore(Node, parent.childNodes.item(Index));
			}
			else
			{
				parent.appendChild(Node);
			}

			return Node;
		};

		/**
		 * remove the given HTML element from the document tree
		 *
		 * @param Node the id or object of the HTML element to be removed
		 * @return HTMLElement
		 * @author Zaïd Sadhoe
		 */

		this.remove = function(Node)
		{
			var node = typeof(Node) == 'string' ? this.getById(Node) : Node;

			return node.parentNode.removeChild(node);
		};

		/**
		 * Add the given attributes to an HTML element
		 *
		 * @param Node the id or object of the HTML element to be removed
		 * @param Attributes an Object with keys and value pairs
		 * @return void
		 * @author Zaïd Sadhoe
		 */

		this.setAttributes = function(Node, Attributes)
		{
			var node = typeof(Node) == 'string' ? this.getById(Node) : Node;

			if(typeof(Attributes) == 'object')
			{
				for(var a in Attributes)
				{
					node.setAttribute(a, Attributes[a]);
				}
			}
		};

		/**
		 * Add the given styles to an HTML element
		 *
		 * @param Node the id or object of the HTML element to be removed
		 * @param Styles an Object with keys and value pairs
		 * @return void
		 * @author Zaïd Sadhoe
		 */

		this.setStyles = function(Node, Styles)
		{
			var node = typeof(Node) == 'string' ? this.getById(Node) : Node;

			if(typeof(Styles) == 'object')
			{
				for(var a in Styles)
				{
					node.style[a] = Styles[a];
				}
			}
		};

		/**
		 * Get the HTML element from the given id
		 *
		 * @param the id of the HTML element
		 * @return HTMLElement
		 * @author Zaïd Sadhoe
		 */

		this.getById = function(Id)
		{
			if(document.getElementById)
			{
				return document.getElementById(Id);
			}
			else if(document.all)
			{
				return document.all[Id];
			}
			else
			{
				return (document[Id] ? document[Id] : window[Id]);
			}
		};
	};


	/**
	 * Update the Date Object with julian date
	 *
	 * @author Zaïd Sadhoe <zaid@ooip.nl>
	 */

	Date.prototype.getJulian = function()
	{
		return Math.floor((this / 86400000) - (this.getTimezoneOffset() / 1440) + 2440587.5);
	}
