function FilterSet(filterTarget, collectionItemSelector, noResultsHandler) {
	var self = this;
	this.collectionItemSelector = collectionItemSelector;
	this.filters = new Array();
	this.activeFilter = null;
	this.filterTarget = $(filterTarget);
	this.noResultsHandler = noResultsHandler || function(){};
	this.resetElement = null;

	this.addFilter = function(){
		var filter = new Filter(self);
		self.filters.push(filter);
		return filter;
	}
	
	this.activateFilter = function(theFilter){
		self.activeFilter = theFilter;
		self.resetInactiveFilters();
		self.updateResetElement();
	}
	
	this.resetAllFilters = function(){
		for (var i = 0; i < self.filters.length; i++) {
			var filter = self.filters[i];
			filter.resetAllFilterParts();
		}
		self.activeFilter = null;
		self.updateResetElement();
		self.noResultsHandler();
	}
	
	this.updateResetElement = function(){
		if (self.resetElement != null) {
			if (self.activeFilter != null) {
				self.resetElement.show();
			} else {
				self.resetElement.hide();
			}
		}
	}

	this.ensureActiveFilter = function(theFilter){
		if (self.activeFilter != theFilter) {
			self.activateFilter(theFilter);
		}
	}

	this.resetInactiveFilters = function(){
		for (var i = 0; i < self.filters.length; i++) {
			var filter = self.filters[i];
			if (filter != self.activeFilter) {
				filter.resetAllFilterParts();
			}
		}
	}
}

function Filter(filterSet) {
	var self = this;
	this.filterSet = filterSet;
	this.filterParts = new Array();
	this.filtervalue = '';
	this.searchScope = '';
	this.mustReset = true;

	this.createFilterPart = function(thePartType, theElement){
		var filterPart = null;
		
		if (thePartType == 'select') {
			filterPart = new FilterPartSelect(theElement, self);
		}
		
		if (thePartType == 'text') {
			filterPart = new FilterPartText(theElement, self);
		}
		
		self.filterParts.push(filterPart);
		self.filterParts[filterPart.id] = filterPart;
		return filterPart;
	}
	
	this.addFilterPart = function(filterPart){
		self.filterParts.push(filterPart);
		self.filterParts[filterPart.id] = filterPart;
	}
	
	this.apply = function(){
		self.filtervalue = "";
		self.filterSet.ensureActiveFilter(self);

		for (var i = 0; i < self.filterParts.length; i++) {
			var filterPart = self.filterParts[i];
			if (filterPart.active) {
				self.filtervalue += " " + filterPart.getValue();
			}
		}

		$.uiCollectionFilter( self.filterSet.filterTarget, self.filterSet.collectionItemSelector, self.filtervalue, self.searchScope );
		self.filterSet.noResultsHandler(self.filterSet.filterTarget.find(self.filterSet.collectionItemSelector + ":visible").length == 0);
		self.resetInactiveFilterParts();
	}
					
	this.clearFiltering = function(){
		$.uiCollectionFilter( self.filterSet.filterTarget, self.filterSet.collectionItemSelector, '' );
	}
	
	this.resetInactiveFilterParts = function(){
		for (var i = 0; i < self.filterParts.length; i++) {
			var filterPart = self.filterParts[i];
			if (!filterPart.active) {
				filterPart.reset();
			}
		}
	}
	
	this.resetAllFilterParts = function(){
		self.clearFiltering();
		for (var i = 0; i < self.filterParts.length; i++) {
			var filterPart = self.filterParts[i];
			filterPart.reset();
		}
	}
}

function FilterPartSelect(theElement, theFilter) {
	var self = this;
	this.elem = theElement;
	this.filter = theFilter;
	this.id = theElement.attr('id');
	this.optionsClone = null;
	this.active = false;
	this.filterValuesContainerSelector = '';
	this.sortOptionsPref = true;
	
	self.filter.addFilterPart(self);
	var firstOptionClone = self.elem.find('option:eq(0)').clone(true);
	theElement.change(function(){self.filterChange(theElement)});
	
	this.init = function(filterValuesContainerSelector){
		self.filterValuesContainerSelector = self.filter.filterSet.collectionItemSelector + ':visible > ' + filterValuesContainerSelector;
		
		if (self.sortOptionsPref){
			self.sortOptions();
		}
		self.optionsClone = self.elem.find('option').clone(true);

		self.reset();
	}
	
	this.sortOptions = function(){
		self.elem.find('option:eq(0)').replaceWith();
		self.elem.sortOptions();
		firstOptionClone.insertBefore(self.elem.find('option:eq(0)'));
	}

	this.getValue = function(){
		var value = "";
		value = self.elem.val();
		return value;
	}

	this.filterChange = function(elem){
		var nothingSelected = (self.elem.find('option:selected').length == 0);
		var firstSelected = (self.elem.find('option:eq(0)').attr('selected'));
		
		if (nothingSelected || firstSelected) {
			self.reset();
		} else {
			self.activate();
		}
		$('body').focus();
		self.filter.apply();
	}
	
	this.activate = function(){
		if (self.filter.mustReset) {
			self.elem.find('option:eq(0)').text('Reset Filter');
			self.elem.find('option:gt(0)').not(':selected').replaceWith();
		}
		self.active = true;
	}
	
	this.reset = function(){
		self.elem.html($(self.optionsClone).clone(true));
		self.active = false;

		var values = "";
		var valuescollection = new Array();
		$(self.filterValuesContainerSelector).each(function(){
			var elem = jQuery(this);
			if (values.indexOf(elem.text()) == -1) {
				values += elem.text() + "\r\n";
				valuescollection.push(elem);
			}
		});

		self.elem.find('option:gt(0)').each(function(){
			var elem = jQuery(this);
			if (values.indexOf(elem.attr('value')) == -1) {
				elem.replaceWith();
			}
		});
		
		if (self.elem.find('option').length == 1) {
			self.elem.attr('disabled', 'disabled');
		} else {
			self.elem.attr('disabled', '');
		}
	}
}

function FilterPartText(theElement, theFilter) {
	var self = this;
	this.elem = theElement;
	this.filter = theFilter;
	this.id = theElement.attr('id');
	this.active = false;
	this.filterValuesContainerSelector = '';
	this.origValue = theElement.val();
	
	self.filter.addFilterPart(self);

	theElement.keyup(function(){
		self.activate();
		self.filter.apply();
	});
	
	theElement.focus(function(){
		if (self.elem.val() == self.origValue) {
			self.elem.val('');
		}
	});
	
	theElement.blur(function(){
		if (self.elem.val() == '') {
			self.reset();
		}
	});
	
	this.getValue = function(){
		var value = "";
		value = self.elem.val();
		return value;
	}
	
	this.activate = function(){
		self.active = true;
	}
	
	this.reset = function(){
		self.active = false;
		self.elem.attr('value',self.origValue);
	}
					
	this.init = function(filterValuesContainerSelector){
		self.filterValuesContainerSelector = self.filter.filterSet.collectionItemSelector + ':visible';
		self.reset();
	}
}

