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

// language strings
jQuery.i18n.addDictionary({
	'MAXSUPPLIERSELECTIONS': "You can't select more than 10 suppliers at a time."
});

;(function($) {
	
	$.fn.DemandMap_SupplierControl = function(mapSelector, _options) { 
		var defaults = {
			'maxNetworkSelections': 10,
			'loadingIndicator': '<div class="loadingIndicator"><img src="cms/images/network-save.gif" /></div>'
		};
		
		return this.each(function(){
			var $this = $(this);
			var container = this;
			
			var options = $.extend({}, defaults, _options);

			// objects
			var map = $(mapSelector);
			var tileLayers = [];
			
			loadSuppliers();
			
			// url config
			if($.jget['hidesearchbar']) $this.hide();

			// add loading indicator
			$('.Actions', container).append(options.loadingIndicator);
			$('.Actions .loadingIndicator', container).hide();
			
			$('.supplierList', container).DemandMap_collapsible();
			
			// Click event for 'limit to networks in this region' checkbox.
			// We can't listen to 'change' as IE6 craps out on this...
			$('#LimitToVisible :input').bind('click', function(e) {
				toggleVisibleSuppliersButton();
			});
			
			// manual refresh
			$('#LimitToVisible a.refresh').livequery('click', function(e) {
				// make sure the checkbox is ticked
				var $input = $(this).parents('label').siblings(':input');
				$input.attr('checked', 'checked');
				toggleVisibleSuppliersButton();
				return false;
			});
			// Event listeners for changes to data filtering.
			// We don't listen to map position changes because of ajax delay/performance reasons
			$(document).bind('DemandSearchBar:searchend', function(e) {
				toggleVisibleSuppliersButton();
			});
			
			// click event of supplier (group) checkbox
			$('.supplierList li.category > :checkbox', container).livequery('click', function(e) {
				var id = $(this).attr('id');					
				var parentState = $(this).attr('checked');
				$('#' + id + ' ul li input').attr('checked', parentState);
				
				var expandCollapse = $(this).parent().children('ul');
				if ( $(this).attr('checked') ) {
					expandCollapse.show();
					disableCollapseButton( $(this), true );
				}
				else {
					disableCollapseButton( $(this), false );
				}
			
				if($(this).attr('checked')) {
					loadSuppliers();
				} else {
					// children (network checkboxes) of the supplier group checkbox
					$(this).parent().children('ul').children('li').children('input:checkbox').each(function() {
						map.fn('clearOverlaysBySupplier', $(this).attr('value'));
					});
				}
				
				return true;
			});
			
			// click event of supplier network checkbox
			$('.supplierList ul li ul li :checkbox', container).livequery('click', function(e) {
				
				tickOrUntickNetworkGroupOf($(this));
				
				// count all already selected checkboxes
				if($('.supplierList :checked', container).length > options.maxNetworkSelections) {
					alert($.i18n._t('MAXSUPPLIERSELECTIONS'));
					e.target.checked = '';
					return false;
				}
				
				var supplierID = e.target.value;
				if(e.target.checked) {
					initTilingForSupplier(supplierID);
				} else {
					map.fn('clearOverlaysBySupplier', supplierID);
				}

				return true;
			});
			
			$('li.category ul li', container).bind('click', function(e) { 
				if ( (hasSelectedChildren($(this).parent())) ) {
					disableCollapseButton( $(this).parent().parent(), true );
				}
				else {
					disableCollapseButton( $(this).parent().parent(), false );
				}
			});
			
			/**
			 * Convenience wrapper around toggleVisibleSuppliers()
			 * which deals with button clicks and states.
			 */
			function toggleVisibleSuppliersButton() {
				$checkbox = $('#LimitToVisible :input');
				$(container).addClass('loading');
				$checkbox.attr('disabled', 'disabled');
				toggleVisibleSuppliers($checkbox.is(':checked'), function(e) {
					$(container).removeClass('loading');
					$checkbox.removeAttr('disabled');
				});
			}
			
			/**
			 * Transfer the current map bounds to the Restful Service
			 * and find out which suppliers have at least one geographical feature
			 * in this area. Used to limit the visible checkbox lists.
			 * 
			 * @param {Boolean} toggle
			 * @param {Function} callback
			 */
			function toggleVisibleSuppliers(toggle, callback) {
				if(toggle) {
					var bounds = map.fn('getQueryBounds');
					var ne = bounds.getNorthEast();
					var sw = bounds.getSouthWest();
					var url = 'api/v1/SupplierNetwork.json?Bounds[sw]=%s,%s&Bounds[ne]=%s,%s&relationdepth=0&fields=ID,SupplierID';
					$.getJSON(
						$.sprintf(url, 
							sw.lng(),
							sw.lat(),
							ne.lng(),
							ne.lat()
						),
						null,
						function(data, status) {
							var ids = jQuery(data.items).map(function() { return this.SupplierID;});
							$('.supplierList .category > :input', container).each(function() {
								if($.inArray($(this).val(), ids) == -1) $(this).parent().addClass('disabled').hide();
							});

							if(callback) callback(data, status);
						}
					);
				} else {
					// reset visibility
					$('.supplierList li', container).removeClass('disabled').show();
					if(callback) callback();
				}
			}
			
			function disableCollapseButton(list, flag) {
				var small = $( 'li#' + $(list).attr('id') + ' small' );
				if (flag) {
					small.html('<span>(' + $.i18n._t('COLLAPSE') + ')</span>');
					small.removeClass('toggle');
				}
				else {
					small.html('(<a href="#">' + $.i18n._t('COLLAPSE') + '</a>)');
					small.addClass('toggle');
				}
			}
			
			/**
			 * Return true if any of children of list are selected, otherwise false
			 */
			function hasSelectedChildren(list) {
				var skip = false;
				
				$(list).children().each(function(){
					var supplierCheckbox = $('#' + $(this).attr('id') + ' input');
		
					if (supplierCheckbox.attr('checked')) {
						skip = true;
						return;
					}
				});
				
				if (skip) return true;
			}
			
			/**
			 * Tick or untick the network group (of the passed-in network) if all of its networks are selected it will be selected 
			 * otherwise, it will be deselected. The passed-in network is a number a checkbox element.
			 */
			function tickOrUntickNetworkGroupOf(network) {
				var networkGroup = network.parent().parent().parent();
				var networks = $('#' + networkGroup.attr('id') + ' ul li :checkbox');
				var selectedNetworks = $('#' + networkGroup.attr('id') + ' ul li :checkbox[@checked]');
				
				// if all of the contained networks are selected, selected the group checkbox as well
				var groupCheckbox = $('#' + networkGroup.attr('id') + ' :checkbox.group');

				//Previosly: if (networks.length == selectedNetworks.length) {
				if (selectedNetworks.length > 0) {
					groupCheckbox.attr('checked', true);
				}
				else {
					groupCheckbox.attr('checked', false);
				}
			}
			
			// load supplier overlayed when they're selected
			function loadSuppliers() {
				var supplierIDs = getSelectedSuppliers();
				$(supplierIDs).each(function(el, i) {
					initTilingForSupplier(i);
				});

				$(document).trigger('SupplierControl:loadSuppliers', [supplierIDs]);
			}
			
			
			// get all the selected Supplier ids 
			function getSelectedSuppliers() {
				return $.map($('input.subcategory:checked', container),function(el, i) {
					if (el.value == parseInt(el.value)) return el.value;
				});
			}
			
			// "show coverage" (toggling of all layers with fake ID '0')
			// radiobutton selection: either "show coverage" or "select networks"
			$('input[name=supplierview]', container).livequery('click', function(e) {
				if(e.target.value == 'showcoverage') {
					// uncheck all existing elements
					$('.supplierList :checkbox', container).each(function() {
						this.checked = '';
						this.disabled = 'disabled';
						$(this).change();
					});
					
					// init or remove tiling
					if(e.target.checked) {
						// clear all supplier overlays
						map.fn('clearOverlaysBySupplier');
						// and re-initialize
						initTilingForSupplier(0);
					} else {
						map.fn('clearOverlaysBySupplier', 0);
					}
				} else {
					$('.supplierList :checkbox', container).each(function() {
						this.disabled = '';
					});
					
					// remove coverage tiling
					map.fn('clearOverlaysBySupplier', 0);
				}
				
			});
			$('form', container).livequery('submit', function(e) {
				$('.Actions .loadingIndicator', container).show();
				
				// clear all overlays (might not be available for deselection in filtered result list)
				map.fn('clearOverlaysBySupplier');

				$(this).load(
					this.action,
					$(':input', this),
					function() {
						$('.Actions .loadingIndicator', container).hide();
					}
				);
				return false;
			});
			
			/**
			 * SupplierID can be '0' which means all overlays are shown at once
			 */
			function initTilingForSupplier(supplierID) {
				// initializing tiling
				var tileLayer = new GTileLayer(new GCopyrightCollection(''));
				
				tileLayer.supplierID = supplierID;
				
				// list node might not exist if ID=0
				if($('#SupplierNetwork' + supplierID).length) {
					var metadata = $('#SupplierNetwork' + supplierID).metadata();
					tileLayer.supplierOpacity = (metadata && typeof(metadata.LayerAlpha) != 'undefined') ? metadata.LayerAlpha : 0.4;
				} else {
					tileLayer.supplierOpacity = 0.4;
				}
				
				tileLayer.getTileUrl = function(tile, zoom) { 
					return 'cache/' + this.supplierID + '/' + tile.x + '-' + tile.y + '-' + zoom + '.gif';
					// Do enable anti-aliased PNGs, use this line instead: 
					// return 'cache/' + this.supplierID + '/' + tile.x + '-' + tile.y + '-' + zoom + '.png'; 
				}
	            tileLayer.isPng = function() { 
					return false; 
				}
	            tileLayer.getOpacity = function() { 
					return this.supplierOpacity; 
				}
				
				tileLayers[supplierID] = new GTileLayerOverlay(tileLayer);
				map.fn('addOverlays', [tileLayers[supplierID]], supplierID);
			}
			
			/*
			function getSelectedSuppliers() {
				var url = 'api/v1/SupplyShape/?SupplierNetworkID=%s&Bounds[sw]=%s,%s&Bounds[ne]=%s,%s&relationdepth=0&add_fields=ParentCategoryID&limit=%d';
				var bounds = map.fn('getQueryBounds');
				var ne = bounds.getNorthEast();
				var sw = bounds.getSouthWest();
				var ids = [];
				
				$('.supplierList :checked').each(function() {
					var id = $(this).val();
					// Get suppliers via json
					$.getJSON(
						$.sprintf(url, 
							id,
							sw.lng(),
							sw.lat(),
							ne.lng(),
							ne.lat(),
							500 // debug
						),
						addEncodedPolygons
						//addPolygons
					);
				});
				
			}
			
			function addPolygons(networkData) {
				var overlays = [];
				// iterate through supplyshape records
				for(var i=0; i<networkData.length; i++) {
					// iterate polygons
					// @todo switch between polygons and polylines
					for(var j=0; j<networkData[i].Polygon.rings.length; j++) {
						var polyPoints = [];
						// iterate rings
						// @todo just render first ring? GPolygon doesn't seem to have support for multi-ring polys
						for(var k=0; k<networkData[i].Polygon.rings[j].points.length; k++) {
							var polyPoint = new GLatLng(networkData[i].Polygon.rings[j].points[k][1], networkData[i].Polygon.rings[j].points[k][0]);
							polyPoints.push(polyPoint);
						}
						var polygon = new GPolygon(polyPoints,"#000000",2,.5,"#000000",.5);
						overlays.push(polygon);
					}
				}
				map.fn('addOverlays', overlays);
			}
			
			function addEncodedPolygons(networkData) {
				var overlays = [];
				var totalVertexCount = 0;
				// iterate through supplyshape records
				for(var i=0; i<networkData.length; i++) {
					// iterate polygons
					// @todo switch between polygons and polylines
					for(var j=0; j<networkData[i].Polygon.rings.length; j++) {
						var polygon = new GPolygon.fromEncoded({
							polylines: [
								networkData[i].Polygon.rings[j].encoded
							],
							fill: true,
							color: "#0000ff",
							opacity: 0.4,
							outline: true
						});
						overlays.push(polygon);
						totalVertexCount += polygon.getVertexCount();
					}
				}
				
				map.fn('addOverlays', overlays);
				
				// debug
				console.log("Showing %d vertices on %d polys", totalVertexCount, overlays.length);
			}
			*/

		});
		
	}
})(jQuery);
