//Code ©2010 Bad Math Inc. (http://www.badmath.com/)
// mapControlAllPoints


/**
mapControlAllPoints extends mapControlBase
to create customized output for the view all points page.
**/
function mapControlAllPoints(map, controlPanelId, customTourTabId, searchTabId, JSONData, defaultStyles, currentSelectionState)
{

	this.prototype = new mapControlBase(map, controlPanelId, customTourTabId, searchTabId, JSONData, defaultStyles); 
	jQuery.extend(true, this, this.prototype);
	
	
	
	this.init = function()
	{   
		
		var self = this;
		if(!this.getCustomTours().length)
		{
			jQuery("#customTourTab").hide();
		}
		
		//set the title
		document.title = "Trip-Click: All Points of Interest";
		
		//set the info box
		//update the instructions
		jQuery("#instructions").empty()
			.append("Browse the map to find places to add to your custom tour." +
				"  Pick a restaurant, a place to stay or anything else that interests you." +
				"  Use the list of categories to the left of the map to narrow your search.");
		
		

		this.initCustomTourTab();
		//this.draw();
		
		//start filtering the JSON to display the markers.
		//loop through each location in the data
		 var filteredJSON = new Object();
		 filteredJSON.markers = new Object();
		jQuery.each(JSONData.markers, function(key, value)
		{
			if(key == null || value == null)
			{
				return true;	
			}
				
			for(var i = 0; i < value.categories.length; i++) {
				if (currentSelectionState[value.categories[i]] == undefined ||
					currentSelectionState[value.categories[i]] == 1) {
					filteredJSON.markers[key] =  self.JSONData.markers[key];
					break;
				}
			}

		}); //end each marker
		
		
		
		
		//this call will cause IE7 to crash when the cache is empty and the map is 
		//being loaded. A slight delay seems to fix the issue.
		if (!jQuery.browser.msie || jQuery.browser.version >= 8) {
			
				this.updateMapWithClusters(filteredJSON, false);
		} else {
			
			window.setTimeout(function() {self.updateMapWithClusters(filteredJSON, false);}, 10);
	
		}
		
		
		
	}
	
	this.getBounds = function() 
	{
		var bounds = null;
		var self = this;
		jQuery.each(self.flusterObject.markers, function(markerKey, markerValue)
		{
			//if (self.flusterObject.markerValue.id {
			if (bounds == null) {	
				bounds = new google.maps.LatLngBounds(markerValue.marker.getPosition());  	
			} else {
				bounds.extend(markerValue.marker.getPosition());
			}
			//}
		});
		if (bounds == null) {
			jQuery.each(self.markersArray, function(markerKey, markerValue)
			{
				if (markerValue.getVisible()) {
					if (bounds === null) {	
						bounds = new google.maps.LatLngBounds(markerValue.getPosition());  	
					} else {
						bounds.extend(markerValue.getPosition());
					}
				}
			});
		}
			
		
		return bounds;
	}	

	
	this.draw = function()
	{
	
		//clear the control Panel Box.
		jQuery("#" + this.controlPanelId).html("");
		
		//start building the control panel
		//create the checkboxes
		var categoryDiv = jQuery("<div/>");
		var categoryDivId = "categoryDiv";
		categoryDiv.attr("id", categoryDivId);
		jQuery("#" + this.controlPanelId).append(categoryDiv);
		this.setSearchEvents(this.searchTabId, this.controlPanelId);
		this.drawCategories(categoryDivId);

	};
	
	//This draws the category checkboxes and
	//assigns their click events.
	//the id of the div to draw into and the
	//object containing the categories
	//are passed in.
	this.drawCategories = function(categoryDivId)
	{
		var allSelected = true;
		var categoryObject = this.JSONData.categories;
	
		//create our show all categories checkbox
		var showAllParagraph = jQuery("<p/>");
		var showAllText = "Show all categories";
		var showAllCheckbox = jQuery('<input type ="checkbox"/>');
		showAllCheckbox
			.attr("name", "checkAll")
			.attr("id", "checkAll");
		showAllParagraph.append(showAllCheckbox).append(showAllText);
		//insert into the dom
		jQuery("#" + categoryDivId).append(showAllParagraph);
		
		//create the accordion div
		var accordionDiv = jQuery("<div/>")
			.addClass("accordion")
			.attr("id","categoryDivId");
				
		var className;
	
		//get the accordion in the dom
		jQuery("#" + categoryDivId).append(accordionDiv);
		
		for(var index = 0; index < categoryObject.length; index++)
		{
			if (currentSelectionState[categoryObject[index].id] == undefined) {
				currentSelectionState[categoryObject[index].id]  = 1;
			}
			//we need to know if there are no subcategories
			//because this case gets a different class assigned
			//to the <h3>
			if(categoryObject[index].categories.length == 0)
			{
				className = "accordHeaderEmpty";
			}
			else
			{
				className = "accordHeader";
			}
			//create the title (only the top title is a accordion header)
			if (currentSelectionState[categoryObject[index].id] == 1) 
			{
				var checkBox = jQuery('<input type="checkbox" checked="checked"/>')
					.attr("id", "chk" + categoryObject[index].id).attr("value", categoryObject[index].id);
			} 
			else 
			{
				allSelected = false;
				var checkBox = jQuery('<input type = "checkbox"/>')
					.attr("id", "chk" + categoryObject[index].id).attr("value", categoryObject[index].id);
			}
			var iconImage = jQuery("<img/>")
				.attr("src", IMAGE_DIRECTORY + categoryObject[index].icon)
				.attr("alt", "Icon");
			var header = jQuery("<h3/>").addClass(className);
			//empty headers require a special empty span be added in
			if(categoryObject[index].categories.length == 0)
			{
				var emptySpan = jQuery("<span/>").addClass("expand empty");
				header.append(emptySpan);
				
			}
			
			header
				.append(checkBox)
				.append(iconImage)
				.append(categoryObject[index].name)
				.attr("id", "headerId" + categoryObject[index].id);
			//add the header into the accordion
			accordionDiv.append(header);
			
			//create the content div
			var contentDiv = jQuery("<div/>")
				.attr("id", "divForId" + categoryObject[index].id)
				.addClass('subCategoryContainer')
				.attr("name", categoryObject[index].id);
			
			//createCategoryHTML is a recursive function that takes care of the multiple
			//nested checkboxes.  It returns a ul.
			contentDiv
				.append(this.createCategoryUL(categoryObject[index].categories, categoryObject[index].id));
			accordionDiv
				.append(contentDiv);
			
		} //end for categories
		
		if (allSelected) {
				showAllCheckbox.attr("checked", "checked");
		}
		
		//add our click function for the check boxes.
		//not: the all categories check box gets a seperate handler
		//this gets redefined by jquery, so we need a pointer to this object
		var self = this;
		jQuery("#" + categoryDivId).find('input[type=checkbox]:not(#checkAll)').click(function(event)
		{	var target = this;
			event.stopPropagation();
			self.categoryClickHandler(target);
		});

		jQuery('#checkAll').click(function()
		{
			var target = this;
			self.allCategoriesClickHandler(target);
			//self.categoryClickHandler(target);
		});
		
		jQuery("#" + categoryDivId).accordion( {
			autoHeight: false,
			header: '.accordHeader',
			icons: {
				'header': 'expand closed',
				'headerSelected': 'expand open'
			},
			collapsible: true
		} );
			
		
	}//end drawCategories
	
	/*
	This function is called
	recursively to build the category <ul> lists.
	CategoryObject contains the info for a category 
	Category Objects contain contain category Arrays
	which in turn can contain category objects that 
	represent subcategories.
	*/
	this.createCategoryUL = function(categoryObject, parentCategoryId)
	{
		if(categoryObject.length == 0)
		{
			return;	
		}

		//create the ul for our category.
		var list = jQuery("<ul/>").addClass("subCats");
		for(var index = 0; index < categoryObject.length; index ++)
		{
			if (currentSelectionState[categoryObject[index].id] === undefined) {
				currentSelectionState[categoryObject[index].id]  = 1;
			}
			var listItem = jQuery("<li/>")
				.attr("name", parentCategoryId);
			if (currentSelectionState[categoryObject[index].id] == 1)  
			{
				var checkBox = jQuery("<input type = 'checkbox' checked = 'checked'/>")
					.attr("id", "chk" + categoryObject[index].id)
					.attr("value", categoryObject[index].id);
			} 
			else 
			{
				var checkBox = jQuery("<input type = 'checkbox'/>")
					.attr("id", "chk" + categoryObject[index].id)
					.attr("value", categoryObject[index].id);
			}
			var iconImage = jQuery("<img/>")
				.attr("src", IMAGE_DIRECTORY + categoryObject[index].icon)
				.attr("alt", "Icon");
			var label = jQuery("<label/>")
				.attr("for", "chk" + categoryObject[index].id)
				.append(iconImage)
				.append(categoryObject[index].name);
			jQuery(listItem)
				.append(checkBox)
				.append(label);
			
			if (categoryObject[index].categories.length)
			{
				//fill in the sub categories
				var subListItem =listItem.append(this.createCategoryUL(categoryObject[index].categories, parentCategoryId));
				jQuery(list).append(subListItem);
			}
			jQuery(list).append(listItem);
		}	
		return list;
	}
	
	/*
	categories click event handler
	When the category checkboxes are clicked, this functuion runs.
	*/
	this.categoryClickHandler = function(target)
	{
		var self = this;
		//we will fill this with the location objects we intend to send to the update map
		//function
		 var filteredJSON = new Object();
		 filteredJSON.markers = new Object();
		 
		
		//if we just unchecked something, lets close the info window
		//and uncheck the parent checkboxes.
		if(!jQuery(target).attr("checked"))
		{
			 self.infoWindow.close();
			
			 var headerParentId = jQuery(target).parent().attr("name");
			 jQuery("#chk" + headerParentId).removeAttr("checked");
			 currentSelectionState[headerParentId] = 0;
			
			jQuery(target).parents().filter("li").each(function() 
			{
				if (jQuery(":first",$(this)).is("input[type = checkbox]")) 
				{
					var itemId = jQuery(":first",$(this)).attr('id').substring("chk".length);
					currentSelectionState[itemId] = 0;
					jQuery(":first",$(this)).removeAttr('checked');
				}
			});

			//uncheck the check all checkbox
			jQuery('#checkAll').removeAttr("checked");
			 
			//if this is a parent category, we want to uncheck all the children.
			var id = jQuery(target).attr("value");
			var parentId = jQuery(target).parent().attr("id");
			
			//set the checked value in the current selection Object
			currentSelectionState[id] = 0;
			
			if(parentId == "headerId" + id)
			{
				//we are a parent.
				jQuery("#divForId" + id).find("input[type = checkbox]").each(function(index, element)
				{
					var itemId = jQuery(element).attr('id').substring("chk".length);
					currentSelectionState[itemId] = 0;
					jQuery(element).removeAttr("checked");																
				}); 
			}
		}
		else //we are checked
		{
			//if this is a parent category, we want to check all the children.
			var id = jQuery(target).attr("value");
			//set the checked value in the current selection Object
			currentSelectionState[id] = 1;
			var parentId = jQuery(target).parent().attr("id");
			if(parentId == "headerId" + id)
			{
				//we are a parent.
				jQuery("#divForId" + id).find("input[type = checkbox]").each(function(index, element)
				{
					var itemId = jQuery(element).attr('id').substring("chk".length);
					currentSelectionState[itemId] = 1;
					jQuery(element).attr("checked","checked");
				}); 
		 	}
			jQuery(target).parents().filter("li").each(function() 
			{
				if (!jQuery(this).children().filter('ul').find('input[type=checkbox]:not(:checked)').length)
				{
					var itemId = jQuery(":first",$(this)).attr('id').substring("chk".length);
					currentSelectionState[itemId] = 1;
					jQuery(":first",$(this)).attr("checked","checked");
				}
			});
			if (jQuery(target).parents().filter('.subCategoryContainer').length &&
				!jQuery(target).parents().filter('.subCategoryContainer').find("input[type = checkbox]:not(:checked)").length) {
				headerParentId = jQuery(target).parents().filter('.subCategoryContainer').attr('id').substring('divForId'.length); 
				jQuery("#chk" + headerParentId).attr("checked","checked");
				 currentSelectionState[headerParentId] = 1;
			}
			if (!jQuery("#categoryDiv").find('input[type=checkbox]:not(#checkAll):not(:checked)').length) {
				jQuery('#checkAll').attr("checked","checked");
			}
		}
		//start filtering the JSON to display the markers.
		//loop through each location in the data
		jQuery.each(JSONData.markers, function(key, value)
		{
			if(key == null || value == null)
			{
				return true;	
			}
			
			for(var i = 0; i < value.categories.length; i++) {
				if (currentSelectionState[value.categories[i]] == undefined ||
					currentSelectionState[value.categories[i]] == 1) {
					filteredJSON.markers[key] =  self.JSONData.markers[key];
					break;
				}
			}
		}); //end each marker
		
		
		self.updateMapWithClusters(filteredJSON, false);
		
	
	};
	/*
	This recursively unchecks parent checkboxes if we are unchecked.
	target is the element that we are starting from
		*/
	this.uncheckParentCheckbox = function(target)
	{
		var self = this;
	
		//this follows the recursivly built dom structure up
		jQuery(target).parent().parent().parent()
		.children("label").children("input")
		.each(function()
		{
			var newTarget = this;
			jQuery(this).unbind('click');
			jQuery(this).attr("checked", false);
			jQuery(this).bind('click', function(event)
			{
				event.stopPropagation();
				self.categoryClickHandler(newTarget);
			});	
			//call recursively
			self.uncheckParentCheckbox(newTarget);
		});
			
	}// end uncheckParentCheckbox
	
	/**
	all categories click handler
	simplify things by ignoring the tree structure in this case
	*/
	this.allCategoriesClickHandler = function(target)
	{
		var self = this;
		 var filteredJSON = new Object();
		 filteredJSON.markers = new Object();
		
		if(jQuery('#checkAll').attr("checked"))
		{
			
			jQuery("#categoryDiv").find('input[type=checkbox]:not(#checkAll)').attr("checked", true);
			for (var i=0 ; i<currentSelectionState.length; i++) {
				currentSelectionState[i] = 1;
			}
			//start filtering the JSON to display the markers.
			//loop through each location in the data
			jQuery.each(JSONData.markers, function(key, value)
			{
				if(key == null || value == null)
				{
					return true;	
				}
				
				for(var i = 0; i < value.categories.length; i++) {
					if (currentSelectionState[value.categories[i]] == undefined ||
						currentSelectionState[value.categories[i]] == 1) {
						filteredJSON.markers[key] =  self.JSONData.markers[key];
						break;
					}
				}
			}); //end each marker	
		}
		else
		{
			jQuery("#categoryDiv").find('input[type=checkbox]:not(#checkAll)').attr("checked", false);
			for (var i=0 ; i<currentSelectionState.length; i++) {
				currentSelectionState[i] = 0;
			}
		}
		
		
		self.updateMapWithClusters(filteredJSON, false);
	
	};
	
		
	this.getType = function()
	{
		return "mapControlAllPoints";
	}

	/*
	This gets the category id that represents the category
	that this marker/location is currently being displayed as.
	In suggested tours, searches, and my custom tour, this is always index 0 (top category)
	In the all points class, this is overrided to give the higest category index that 
	is currently displayed (by checking what checkboxes are checked).
	*/
	this.getMarkerCategoryId = function(locationId)
	{
		//if we're searching, we revert to the base class version
		if(jQuery("#searchTab").hasClass("selected"))
		{
			return this.prototype.getMarkerCategoryId.call(this, locationId);
		}
		
		var markerCategories;
		var categoryId;
		if(this.JSONData.markers.hasOwnProperty(locationId))
		{
			markerCategories =  this.JSONData.markers[locationId].categories;
		}
		else
		{
			if (console && console.log) {
				console.log("getMarkerCategoryId was asked to get the category for id " 
				  + locationId + ", which is not in JSONData");	
			}
			return;
		}
		//find the index of the hightest ranking category for this marker that is displayed.
		for(var index = 0; index < markerCategories.length; index++)
		{
			if(currentSelectionState == [] || currentSelectionState[markerCategories[index]])
			{
				categoryId = markerCategories[index];
				break;
			}
		}
		if(categoryId == null)
		{
			//just return the top category.  This is probably a custom tour that is being overlayed
			categoryId =  this.JSONData.markers[locationId].categories[0];
		}
		return categoryId;
	} //end getMarkerCategoryId
	

} //end mapControlAllPoints

