// TODO implement _t()
var i18n = i18n || {};

jQuery.i18n.addDictionary({
	'EXPAND': "expand",
	'COLLAPSE': "collapse"
});

;(function($) {
	
	$.fn.DemandMap_CategoryControl = function(mapSelector, _options) { 
		
		var defaults = {
			'loadingIndicator': '<div class="loadingIndicator"><img src="cms/images/network-save.gif" /></div>',
			'defaultRegionZoom': 8,
			'redrawDelayMs': 750,
			'allCategoriesChecked': false
		};
		
		return this.each(function(){
			var options = $.extend({}, defaults, _options);
			
			// Reference to this control
			var $this = $(this);
			var container = this;
			
			// objects
			var $map = $(mapSelector);
			
			// state
			// avoid more than one request running at any given moment
			var ajaxManager = $.manageAjax({manageType: 'abortOld', maxReq: 0}); 
			
			// set up ui
			$('#CategoriesHideShowHolder', container).show();
			
			// event handlers
			$(':checkbox', container).bind('click', function(e) {
				
				// remove count from the uncheck categories
				if ($(this).attr('checked') == false) {
					checkboxID = $(this).attr('id');
					prefix = 'DemandCategoryID_';
					numericID = checkboxID.substr(prefix.length, checkboxID.length);

					$('#DemandCategory' + numericID + ' label span.pointCount' ).text('');
				}
				
				if(!Number(e.target.value)) return false;
			
				var categoryID = Number(e.target.value);
				if(e.target.checked) {
					loadCategories(categoryID);
				} else {
					e.target.checked = '';
					unloadCategories(categoryID);
				}
				
				return true;
			});
			
			$('#CategoriesHideShow').unbind('click')
			$('#CategoriesHideShow').click(function(e) {
				if ($(this).attr('checked') == true) {
					loadCategories(null);
				}
				else {
					hideAllCategoriesCounts();
				}
				
			});

			// Update map whenever it moves
			$map.bind('DemandMap:move', function(e, bounds, zoom) {
				loadCategories(null);	
			});
			
			// add loading indicator
			$('#DemandCategoryID li', container).append(options.loadingIndicator);
			$('#DemandCategoryID li .loadingIndicator', container).hide();
			
			$('ul', container).DemandMap_collapsible();
			
			if($.jget['categories']) {
				var categories = $.jget['categories'].split(',');
				for(var i=0; i<categories.length; i++) {
					var categoryEl = $('input[title=' + categories[i] + ']', this).get(0);
					if(categoryEl) categoryEl.checked = 'checked';
				}
			} else if(options.allCategoriesChecked) {
				$(':checkbox', container).each(function(index, el) {
					this.checked = 'checked';
				});
			}
			
			// load all checked points
			loadCategories();
						
			function loadCategories(categoryID) {
				var toplevelCategoryIDs = [];
				if(categoryID && categoryID > 0) {
					toplevelCategoryIDs.push(categoryID);
				} else {
					
				   $('input:checked', container).each(function(index, el) {
				   });
				}
				
				// make sure subcategories are selected
				for(var i=0; i<toplevelCategoryIDs.length; i++) {
				   var isSubcategory = $($.sprintf('input[value=%d]', toplevelCategoryIDs[i]), container).hasClass('subcategory');
					if(!isSubcategory) {
						$('#DemandCategory'+toplevelCategoryIDs[i]+' input.subcategory', container).each(function(index, el) {
							el.checked = 'checked';
						});
					}
				}
				
				var categoryIDs = getSelectedCategories();
				
				if(categoryIDs.length) {
					// set loading indicator
					$this.addClass('loading');
				} else {
					$this.removeClass('loading');
					
					$map.fn('clearMarkers');
					return false;
				}
				
				ajaxManager.add({
					url: getDataURL(),
					success: function(markersJson) {
					    // Get queue size
					    var i,queueSize = 0;
					    for(i=0;i<ajaxManager.queue.length;i++) if(ajaxManager.queue[i]) queueSize++;
					    
					    if(queueSize <= 1) {
            				$this.removeClass('loading');
    						$map.fn('addPoints', markersJson.items);
    						$this.trigger('DemandCategoryControl:loadcategories', [categoryIDs, markersJson.items]);
						}
						
						if( $('#CategoriesHideShow').attr('checked') == true ) {
							// update the total number of item of each category
							showCategoriesCounts(markersJson);
						}
					},
					dataType: 'json'
				});
			}
			
			//showAllCategoriesCounts();
			
			// function showAllCategoriesCounts() {
			// 				$this.addClass('loading');
			// 				
			// 				ajaxManager.add({
			// 					url: getDataURL(true),
			// 					success: function(markersJson) {
			// 					    // Get queue size
			// 					    var i,queueSize = 0;
			// 					    for(i=0;i<ajaxManager.queue.length;i++) if(ajaxManager.queue[i]) queueSize++;
			// 					    
			//             			$this.removeClass('loading');
			// 						
			// 						// update the total number of item of each category
			// 						showCategoriesCounts(markersJson);
			// 					},
			// 					dataType: 'json'
			// 				});
			// 			}
			
			function showCategoriesCounts(markers) {
				var categoriesCount = new Array();

				for (i=0; i<markers.items.length; i++) {
					var item = markers.items[i];
					
					// if the item contain multiple point counts 
					if (typeof item.ClusterCategories != 'undefined') {
						// go through each count
						for(id in item.ClusterCategories) 
						{
							if (isNaN(categoriesCount[id])) categoriesCount[id] = 0;
							
							// get category id
							val = parseInt(item.ClusterCategories[id]);
							categoriesCount[id] += val;
							
							// if this point has a person category then accumulate the count to the parent as well
							parentID = getParentCategoryID(id);						
							if (parentID > -1) {
								if (isNaN(categoriesCount[parentID])) categoriesCount[parentID] = 0;
								categoriesCount[parentID] += val;
							}
						}
							
					}
					// each item represent one point with category id 
					else {
						id = item.CategoryID;
						
						if (isNaN(categoriesCount[id])) categoriesCount[id] = 0;
						categoriesCount[id]++;
						
						// if this point has a person category then accumulate the count to the parent as well
						parentID = getParentCategoryID(id);
						if (parentID > -1) {
							if (isNaN(categoriesCount[parentID])) categoriesCount[parentID] = 0;
							categoriesCount[parentID]++;
						}
					}
					
				}
				
				updateCategoriesCounts(categoriesCount);
			}
		
			/** 
			 * Update categories' label with the number of points
			 * NOTE: put the original label text in to text attribute 
			 * @param 	associative array of points counts of categories
			 * 			for example, countsArray('4' => 120) //where 4 is the category id 
			 */
			function updateCategoriesCounts(countsArray) {
				for (key in countsArray) {
					if ( isNaN(parseInt(key)) ) continue;
					
					var countSpan = $('#DemandCategory' + key + ' label:first span.pointCount');
					countSpan.text( countsArray[key] );
				}
			}
			
			function hideAllCategoriesCounts() {
				
				jQuery('li.category label span.pointCount').each(function(){
					span = $(this);
					span.text('');
				});
			}
		
			function getParentCategoryID(categoryID) {
				idPrefix = 'DemandCategory';
				
				parentDOMID = $('#' + idPrefix + categoryID).parent().parent().attr('id');
				if (parentDOMID && parentDOMID.indexOf(idPrefix) > -1) {
					prefixLen = 'DemandCategory'.length;
					id = parentDOMID.substr( prefixLen,  categoryID.length);
					return id+'';
				}
				
				return -1;
			}
			
			
			function unloadCategories(categoryID) {
				if(categoryID) {
					var isSubcategory = $($.sprintf('input[value=%d]', categoryID), container).hasClass('subcategory');
					if(!isSubcategory) {
						$('#DemandCategory'+categoryID+' input.subcategory', container).each(function(index, el) {
							el.checked = '';
						});
					}
				}
				
				ajaxManager.abort();
				
				loadCategories();
			}
			
			function getDataURL() {
				var url = jQuery('base').attr('href') +  'api/v1/DemandPoint.json?CategoryID=%s&Bounds[sw]=%s,%s&Bounds[ne]=%s,%s&relationdepth=0&add_fields=ParentCategoryID'; 

				var bounds = $map.fn('getQueryBounds');
				var ne = bounds.getNorthEast();
				var sw = bounds.getSouthWest();

				var categoryIDs = getSelectedCategories();
				//if (getAll == true) categoryIDs = getAllCategories();
				
				// avoid returning all points when no categories are selected by forcing a pseudo categoryid
				if(!categoryIDs || !categoryIDs.length) categoryIDs = [-1];
				
				if($.jget['owneremail']) url += '&OwnerEmail=' + $.jget['owneremail'];
				if($.jget['ownerid']) url += '&OwnerID=' + Number($.jget['ownerid']);
				
				return $.sprintf(url,
					categoryIDs.join(','),
					sw.lng(),
					sw.lat(),
					ne.lng(),
					ne.lat()
				);
			}
			
			function getSelectedCategories() {
				return $.map($('input.category:checked, input.subcategory:checked', container),function(el, i) {
					return el.value;
				});
			}
			
			function getAllCategories() {
				return $.map($('input', container),function(el, i) {
					return el.value;
				});
			}
			
			function _setLoading(isLoading, categoryID) {
				var el = $($.sprintf('input[value=%s]', categoryID), container)[0];
				if(isLoading) {
					//el.checked = '';
					//el.disabled = true;
					$('.loadingIndicator', el.parentNode).show();
					$(el.parentNode).addClass('loading');
				} else {
					//el.checked = 'checked';
					//el.disabled = '';
					$('.loadingIndicator', el.parentNode).hide();
					$(el.parentNode).removeClass('loading');
				}
			}
			
			function abortAjaxProcesses() {
				for(var i=0; i<_ajaxProcesses.length; i++) {
					if(typeof _ajaxProcesses[i].abort != 'undefined') _ajaxProcesses[i].abort();
					if(typeof _ajaxProcesses[i].close != 'undefined') _ajaxProcesses[i].close();
				}
				
				_ajaxProcesses = [];
			}
			
			// ######## public methods #########
			$this.fn({
				'getDataURL' : function() {
					return getDataURL();
				},
				'loadCategories' : function() {
					loadCategories();
				},
				'getSelectedCategories' : function() {
					return getSelectedCategories();
				}
			});
		});
	}
})(jQuery);