function CategoryFilter() {
	$svGM = jQuery.fn.svGoogleMaps;
	
	this.filterByZero = false;
	var self = this;
	//Expects an array of placemarks, returns array of all unfiltered placemarks
	this.run = function() {
		$svGM.updatedFilters(this.applyFilter($svGM.args.placemarks[$svGM.args.mapName], this.getValue()));
	}
	
	this.applyFilter = function(arr,value){
		var unfiltered = new Array();
		var catIDs = new Array();
		var catIconStyles = $svGM.args.maps[$svGM.args.mapName].catIconStyles.slice(0);
		//First reset any existing filter
		this.resetFilter(arr);

		//Now apply the new value
		for (var i = 0; i < arr.length; i++) {
			arr[i].filteredBy['catid'] = true;
			for (var j = 0; j < value.length; j++){
				if (arr[i].subcatid == value[j]) {
					arr[i].filteredBy['catid'] = false;
					break;
				}
				if ($svGM.args.categories[value[j]])
					arr[i].filteredBy['catid'] = jQuery.inArray(parseInt(arr[i].prikey), $svGM.args.categories[value[j]]) < 0;
			}
			arr[i].filtered = arr[i].filtered || arr[i].filteredBy['catid'] || !arr[i].active;
			if(!arr[i].filtered) {
				if (jQuery.inArray(arr[i].catid, catIDs) < 0)
					catIDs.push(arr[i].catid);
				unfiltered.push(arr[i]);
			}
		}
		for (var z = 0; z < catIDs.length; z++) {
			catIconStyles.push(catIDs[catIDs.push({'catID': catIDs.shift(), 'style': catIconStyles.shift()}) - 1].style)
		}
		for (var i = 0; i < unfiltered.length; i++) {
			for (var z = 0; z < catIDs.length; z++) {
				if (catIDs[z].catID == unfiltered[i].catid) {
					unfiltered[i].iconstyle = catIDs[z].style;
				}
			}
		}
		return unfiltered;
	}

	//Expects an array of placemarks
	this.resetFilter = function(arr){
		for(var i = 0; i < arr.length; i++){
			//Reset this filter
			arr[i].filteredBy['catid'] = false;
			arr[i].filtered = false;
			//Reapply Filter if there are any additional filters
		}
		this.checkFilters(arr);
	}

	//Expects an array of placemarks - will check all filters and reset filter status based on that
	this.checkFilters = function(arr){
		for (var i = 0; i < arr.length; i++) {
			arr[i].filtered = false;
			for(var j in arr[i].filteredBy) {
				arr[i].filtered = arr[i].filtered || arr[i].filteredBy[j];
			}
		}
	}
	
	this.catToggle = function() {
		if (!jQuery(this).parent('div').siblings('div.gSubCatList').length)
			return false;
		
		if (jQuery(this).parent('div').siblings('div.gSubCatList:visible').length == 0)
			jQuery(this).parent('div').siblings('div.gSubCatList').addClass("gExpanded");
		else {
			jQuery(this).parent('div').siblings('div.gSubCatList').removeClass("gExpanded");
		}
		jQuery(this).parent("div").siblings('div.gSubCatList').toggle('normal', function() { jQuery().trigger('cbox_resize'); });
		return false;
	}

	this.catClicked = function(){
		if(jQuery(this).is(":checked")) {
			jQuery(this).parent("div").parent("li").find("input" + $svGM.args.subCatFilterTitle).attr("checked", "true");
			jQuery(this).parent('div').siblings('div.gSubCatList').addClass("gExpanded");
			//jQuery(this).parent("div").siblings("div.gSubCatList").slideDown('normal', function() { jQuery().trigger('cbox_resize'); });
			jQuery(this).parent('div').siblings('div.gSubCatList').show('normal');
		} else {
			jQuery(this).parent("div").parent("li").find("input" + $svGM.args.subCatFilterTitle).removeAttr("checked");
			jQuery(this).parent('div').siblings('div.gSubCatList').removeClass("gExpanded");
			//jQuery(this).parent("div").siblings("div.gSubCatList").slideUp('normal', function() { jQuery().trigger('cbox_resize'); });
			jQuery(this).parent('div').siblings('div.gSubCatList').hide('normal');
		}
		//jQuery().trigger('cbox_resize');
		self.run();
	}

	this.subcatClicked = function() {
		if(!jQuery(this).is(":checked"))
		{
			$cat = jQuery(this).parents("li.cat").find("input" + $svGM.args.catFilterTitle);
			if($cat.siblings("ul").find("input:checked").length < $cat.siblings("ul").find("input").length)
				$cat.removeAttr("checked");
		}
		self.run();
	}
	
	this.getValue = function(){
		var subcatlist = jQuery($svGM.args.subCatFilterTitle);
		var valueArr = new Array();
		for (var i = 0; i < subcatlist.length; i++){
			if(subcatlist[i].checked){
				valueArr.push(subcatlist[i].value);
			}
		}
		return valueArr;
	}
	
	//Initialize Event Handlers for Category Filter
	this.init = function() {
		jQuery('label.gCatTitle').click(self.catToggle);
		jQuery($svGM.args.catFilterList + ' div.gCatTitle input').click(self.catClicked);
		jQuery($svGM.args.subCatFilterTitle).click(self.subcatClicked);
	}
	
	this.init();
}
