var DataFilter = new Class(
{	
	/*				--[ FIELDS ]--
	
	filterFields		// filter data from initialization
	resultsColumns		// column data from initialization 
	response			// latest response from server 
	requestId			// latest request ID
	filterState			// filter state object
	waitCount 			// current number of outstanding requests  		 
	printFlag			// print results when the last request returns
	
	*/
	
	defaultOptions: 
	{  
		permanentCriteria: 	{ },
		start: 				1, 
		size: 				10
	},
	
	
	/*				--[ CONSTRUCTOR ]--
	 */
	initialize: function(options)
	{
		this.options = $extend(this.defaultOptions, options);
		this.waitCount = 0;
		this.filterState = this.parseQuery(window.location.search);//Cookie.read(this.options.cookieName) ||
			
	},
	
	
	/*				--[ CHECKBOX CLICK HANDLER ]--
	 */
	toggleFilterOption: function(id)
	{	
		var checkbox = $(id);
		if(checkbox)
		{
			if(!this.filterState.filters[checkbox.name])
			{
				this.filterState.filters[checkbox.name] = { };
			}
			
			this.filterState.filters[checkbox.name][checkbox.value] =
				checkbox.checked;
		}
		
		this.filterState.start = this.options.start;
		this.filterState.size = this.options.size;
		this.requestData();
	},
	
	
	/*				--[ SORT HANDLER ]--
	 */
	sort: function(field)
	{
		if(this.filterState.sortBy == field)
		{
			this.filterState.sortOrder = 
				(this.filterState.sortOrder == "asc") ? "desc" : "asc";
		}
		else
		{
			this.filterState.sortBy = field;
			this.filterState.sortOrder = this.options.sortOrder;
		}
		
		this.requestData();
	},
	
	
	/*				--[ GO TO SPECIFIED RESULTS PAGE ]--
	 */
	showPage: function(page)
	{
		this.filterState.size = this.options.size;
		this.filterState.start = ((page - 1) * this.filterState.size) + 1;
		this.requestData();
	},
	
	
	/*				--[ SHOW ALL RESULTS ]--
	 */
	showAll: function()
	{
		this.filterState.size = 9999;
		this.filterState.start = this.options.start;
		this.requestData();
	},
	
	
	/*				--[ SHOW PAGED RESULTS ]--
	 */
	showPaged: function()
	{
		this.filterState.size = this.options.size;
		this.filterState.start = this.options.start;
		this.requestData();
	},
	
	
	/*				--[ LOAD ALL RESULTS AND PRINT THEM ]--
	 */
	print: function()
	{
		this.printFlag = true;
		this.showAll();
	},
	
	
	/*				--[ MAKE REQUEST TO SERVER ]--
	 */
	requestData: function()
	{
		var params = this.filterState;
		this.requestId = params["id"] = new Date().getTime();
		
		var queryString = this.createQueryString(params);
		//Cookie.write(this.options.cookieName, queryString, { path: "/", duration: false });
		this.showLoadingIndicator();
		
		// insert <script> to load data
		
		var script = document.createElement("script");
		script.type = "text/javascript";
		script.id = "request_" + params.id;
		script.src = this.options.requestURL + "?" +
			queryString;
			
		
		$$("head")[0].appendChild(script);
	},
	
	
	/*				--[ LOAD DATA FROM AJAX CALL ]--
	 */
	LoadData: function(response)
	{
	
		if(!this.requestId)
		{
		
			this.response = response;
			this.filterFields = response.initialization.filters;
			this.resultsColumns = response.initialization.results;	
				
		}
		else 
		{
			this.hideLoadingIndicator();			
			if(response.id == this.requestId)
			{
				this.response = response;
				this.displayResponse();
			}
		}
		
		// check for print flag
		if(this.printFlag)
		{
			this.printFlag = false;
			(function(){ window.print(); }).delay(20);
		}
		
		// remove the leftover <script> element
		var scriptElement;
		if((response.id && (scriptElement = $("request_" + response.id))) ||
			(scriptElement = $("request_init")))
		{
			//scriptElement.parentNode.removeChild(scriptElement);
		}
	},
	
	
	/*				--[ DISPLAY RESPONSE FROM SERVER ]--
	 */
	displayResponse: function()
	{
		Bumble.Update("filter_container", FilterTemplate, { app: this });
		Bumble.Update("results_container", ResultsTemplate, { app: this });
	},	
	
	
	/*				--[ PARSE QUERY STRING TO FILTER STATE ]--
	 */
	parseQuery: function(query)
	{
		// remove unwanted segments
		query = query.replace(/^\?/, "");		  // ?
		query = query.replace(/&?id=\d+/, "");	  // id=XXX
		query = query.replace(/&?init=true/, ""); // init=true
		
		var params = { filters: { } };		
		var groups = query.split("&");
		for(var i=0;i<groups.length;i++)
		{
			var pair = groups[i].split("=");
			if(pair.length == 2)
			{
				var values = null;
				switch(pair[0])
				{
					case "sortBy":
					case "sortOrder":
					case "start":
					case "size":											
						params[pair[0]] = pair[1];
						break;												
					default:
						params.filters[pair[0]] = { };
						values = pair[1].split(/;|%3B/i);
						for(var j=0;j<values.length;j++)
						{
							params.filters[pair[0]][decodeURIComponent(values[j])] = true;
						}
				}
			}
		}
		
		// set defaults
		params.sortBy = params.sortBy || this.options.sortBy;
		params.sortOrder = params.sortOrder || this.options.sortOrder;
		params.start = parseInt(params.start) || this.options.start;
		params.size = parseInt(params.size) || this.options.size;

		return params;
	},
	
	
	/*				--[ TRANSLATE FILTER STATE INTO QUERY STRING ]--
	 */
	createQueryString: function(params)
	{
		var expanded = { };
		
		for(i in params)
		{
			if(i != "filters")
			{
				expanded[i] = params[i];
			}
			else
			{
				var filterSets = 
				[ 
					params.filters,
					this.options.permanentCriteria 
				];
				
				for(var x=0;x<filterSets.length;x++)
				{
					for(j in filterSets[x])
					{
						var values = [ ];
						for(k in filterSets[x][j])
						{
							if(filterSets[x][j][k])
							{
								values.push(k);
							}
						}
					
						if(values.length > 0)
						{
							expanded[j] = values.join(";");
						}
					}
				}
			}
		}
		
		var result = [];
		for(var i in expanded) 
		{
			result.push(encodeURIComponent(i) + '=' + 
				encodeURIComponent(expanded[i]));
		}
		
		return result.join('&');
	},
	
	
	/*				--[ "FILTERING BY" MESSAGE ]--
	 */
	getFilterByString: function()
	{
		var filterValues = [ ];
		for(f in this.filterState.filters) 
		{
			var optionValues = [ ];
			for(o in this.filterState.filters[f])
			{
				if(this.filterState.filters[f][o])
				{
					optionValues.push(o);
				}
			}
			
			if(optionValues.length > 0)
			{
				var filterTitle = null;
				for(var i=0;i<this.filterFields.length;i++)
				{
					if(this.filterFields[i].name == f)
					{
						filterTitle = this.filterFields[i].title;
						break;
					}
				}
				
				if(filterTitle)
				{
					filterValues.push(filterTitle + ": " + optionValues.join(", "));
				}
			}
		}
		
		return (filterValues.length > 0 ? filterValues.join("; ") : null);
	},
	
	
	/*				--[ SHOW / HIDE LOADING INDICATOR ]--
	 */
	showLoadingIndicator: function()
	{
		this.waitCount++;
		//$("spinner").style.display = "block";
	},
	
	hideLoadingIndicator: function()
	{
		if(--this.waitCount <= 0)
		{
			//$("spinner").style.display = "none";
		}
	},
	
	
	/*				--[ HTML GENERATORS ]-- 
	 */
	
	getInitCode: function()
	{		
		var params = $extend({ }, this.filterState);
		params.init = true;
		
			return "<script id=\"request_init\" type=\"text/javascript\" src=\"" + 
			this.options.requestURL + "?" +
			this.createQueryString(params) + "\"></script>";
	},
		
	writeFilterCode: function()
	{
		return Bumble.Inline(FilterTemplate, { app: this });
	},
	
	writeResultsCode: function()
	{
		return Bumble.Inline(ResultsTemplate, { app: this });
	}
	
});

