var LocationChooser = {
	
	locationTypes: new Array('Park', 'Center', 'District'),
	locations: new Array(),
	type: 'Park', // currently selected location type to filter
	elm: false,	// storing jquery instance of LocationChooser html dom
	map: false, // jquery map element
	
	// startup called in appcontroller index
	initialize: function() {
		this.elm = $('#LocationChooser');
		this.map = this.elm.find('.map');
		
		// overwrite all links from json array with links from ul lists
		for(i in LocationData) {
			var Locations = LocationData[i];
			for(j in Locations) {
				var Location = Locations[j];
				LocationData[i][j].url = $('.location'+ Location.id + ' a').attr('href');
			}
		}
		
		// get last state from cookie
		if ($.cookie('LocationChooser.type')) {
			this.type = $.cookie('LocationChooser.type');
		}
		
		// initially hide location type list that is not active
		this.elm.find('ul:not(.' + this.type + ') li.sub').hide();
		// set on click handler for list accordion
		this.elm.find('a.toggleTypeList').click(function() {
			var type = $(this).parents('ul').attr('class');
			LocationChooser.toggleTypeList(type);
		});
		
		// sectors / services checkboxes
		// ----------------------------
		// change handler updates Locations list and map points
		// on/off all checkboxes
		$('.toggleParentCheckboxes').click(function() {
			$(this).parent().parent().find('input[type=checkbox]').attr('checked', $(this).parent().parent().find('input[type=checkbox]:checked').length == 0);
			LocationChooser.update();
			return true;
		})
		// sector / services list slideopen when clicked
		$('.sectors ul li span, .services ul li span').click(function() {
			var subList = $(this).parent().find('ul');
			if (subList.length == 0) return true;
			if (subList.find(':visible').length > 0) {
				$(this).parent().find('ul').slideUp();
			} else {
				$(this).parent().find('ul').slideDown();
			}
			return true;
		});
		// sector / services header checkboxes check/uncheck sub checkboxes
		$('.sectors ul li input[type=checkbox], .services ul li input[type=checkbox]').click(function() {
			var subList = $(this).parent().find('ul');
			if (subList.length == 0) return true;
			subList.find('input[type=checkbox]').attr('checked', $(this).attr('checked'));
			return true;
		});
		// deselect parent checkbox if all sub checkboxes off
		$('.sectors ul li ul input[type=checkbox], .services ul li ul input[type=checkbox]').click(function() {
			if ($(this).attr('checked')) return true;
			if ($(this).parent().parent().find('input[type=checkbox]:checked').length == 0) {
				$(this).parent().parent().parent().find('input[type=checkbox]:first').attr('checked', false);
			}
			return true;
		});
		this.elm.find('.sectorLists input[type=checkbox]').click(function() {
			LocationChooser.update();
			return true;
		});
		return this;
	},
	
	collectCheckBoxValues: function(checkboxes)
	{
		var ids = new Array();
		if (checkboxes.length > 0) for(i = 0; i < checkboxes.length; i++) {
			ids.push($(checkboxes[i]).val());
		};		
		return ids;
	}, 
	
	getSelectedSectorIds: function()
	{
		return this.collectCheckBoxValues(this.elm.find('.sectors input[type=checkbox]:checked'))
	},
	
	getSelectedServiceIds: function()
	{
		return this.collectCheckBoxValues(this.elm.find('.services input[type=checkbox]:checked'))
	},
	
	inArray: function(needle, haystack) {
		for(index in haystack) {
			if (haystack[index] == needle) return true;
		}
		return false;
	},
	
	update: function()
	{
		// collect current state
		var selectedSectors = this.getSelectedSectorIds();
		var selectedServices = this.getSelectedServiceIds();
		// filter lists
		this.clearPoints();
		this.locations = this.filterLocations(selectedSectors, selectedServices);
		for (var type in this.locations) {
			// get list and clear list
			var list = this.elm.find('.LocationLists ul.' + type);
			var headline = list.find('li a.header em').html('(' + this.locations[type].length + ')');
			var entries = '';
			for (var i = 0; i < this.locations[type].length; i++) {
				var Location = this.locations[type][i];
				if (type == this.type) {
					this.addPoint(Location);
				}
				entries += '<li class="location' + Location.id + '"><a href="' + Location.url + '" title="' + Location.name + '">' + Location.name + '</a></li>'
			}
			list.find('li.sub ul').html(entries);
			// add event listener
			list.find('li.sub ul li').hover(function() {
				var locationId = parseInt($(this).attr('class').match(/\d+/));
				LocationChooser.map.find('.point'+locationId).addClass('hover');
			}, function() {
				var locationId = parseInt($(this).attr('class').match(/\d+/));
				LocationChooser.map.find('.point'+locationId).removeClass('hover');
			});
		}
	},
	
	/**
	 * Return a list of locations with the passes sectors and services
	 * @param array sectors
	 * @param array services
	 * @return array
	 */
	filterLocations: function(sectors, services) 
	{
		var Locations = [];
		for(i = 0; i < this.locationTypes.length; i++) {
			var type = this.locationTypes[i];
			Locations[type] = [];
			if ('undefined' == typeof(LocationData[type])) continue;
			for(j = 0; j < LocationData[type].length; j++) {
				var Location = LocationData[type][j];
				var add = false;
				// only filter sectors and districts when anything selected
				for(k = 0; k < sectors.length; k++) {
					add += this.inArray(sectors[k], LocationSector[Location.id]);
				}
				for(k = 0; k < services.length; k++) {
					add += this.inArray(services[k], LocationService[Location.id]);
				}
				if (add) {
					Locations[type].push(Location);
				}
			}
		}
		return Locations;
	},
	
	showPoints: function(type)
	{
		this.clearPoints();
		for(i in this.locations[type]) {
			this.addPoint(this.locations[type][i]);
		}
		return this;
	},
	
	between: function(value, min, max)
	{
		return (value > min && value < max);
	},
	
	latLngToXYCache: new Array(),
	latLngToXY: function(lat, lng, height, width){
		longitude_shift = 0;
	    x = ((width * (180 + lng) / 360) % width) + longitude_shift;
	    // latitude: using the Mercator projection
	    lat = lat * Math.PI / 180;  // convert from degrees to radians
	    y = Math.log(Math.tan((lat/2) + (Math.PI/4)));  // do the Mercator projection (w/ equator of 2pi units)
	    y = (height / 2) - (width * y / (2 * Math.PI)) + 0;   // fit it to our map
		// scale
		x = (x-171.6) * 25.3;
		y = (y-92) * 25.3;
		var ret = {
			'x': Math.round(x),
			'y': Math.round(y)
		};
		// check if coordinates allready in use and set point a bit more
		// to the right, so no points are double placed
		var pSize = 8;
		ret.x -= Math.round(pSize/2);
		ret.y -= Math.round(pSize/4);
		for(i = 0; i < this.latLngToXYCache.length; i++) {
			var old = this.latLngToXYCache[i];
			if (this.between(ret.x, old.x - pSize, old.x + pSize)) {
				if (old.y == ret.y) {
					ret.x = old.x - pSize;					
				}
			}
		}
		this.latLngToXYCache.push(ret);
		return ret;
	},
	
	/**
	 * add one point for the passed Location object to the map
	 *
	 * @param object Location
	 * @return object
	 */
	addPoint: function(Location)
	{
		if (Location.lat + Location.lng == 0) return this;
		// calculate position on map
		var xy = this.latLngToXY(Location.lat, Location.lng, 282, 331);
		// create point
		var point = $('<a href="' + Location.url + '" class="point point' + Location.id +' ' + Location.model + '" title="' + Location.name + '">&nbsp;</a>');
		this.map.append(point);
		point.data('Location', Location);
		point.hover(function() {
			var Location = $(this).data('Location');
			$('li.location' + Location.id).addClass('hover');
		}, function() {
			var Location = $(this).data('Location');
			$('li.location' + Location.id).removeClass('hover');
		});
		// append point to map
		point.css({
			'z-index': this.map.find('.point').length + 10,
			'marginLeft': xy.x + 'px',
			'marginTop': xy.y + 'px',
			'position': 'absolute'
		});
		return this;
	},
	
	/**
	 * Delete all points from the map
	 */
	clearPoints: function()
	{
		this.latLngToXYCache = new Array();
		this.map.find('.point').remove();
		return this;
	},
	
	/**
	 * select different kind of location type
	 * @param string type
	 * @return object
	 */
	toggleTypeList: function(type)
	{
		// do nothing if allready selected
		if (type === this.type) return this;
		// hide previous opened list and show new list
		this.elm.find('ul.' + this.type + ' li.sub').hide();
		this.type = type;
		this.elm.find('ul.' + this.type + ' li.sub').slideDown();
		this.showPoints(this.type);
		// save last opened type in cookie
		$.cookie('LocationChooser.type', this.type, { expires: 356, path: '/' });
		return this;
	}
};

if ($.browser.msie) {
	$('#LocationChooser .LocationLists ul').css('backgroundColor', '#ffffff');
}

$(document).ready(function() {
	
	// get webroot
	var webroot = $('base').attr('href');
	
	// initialize lightbox
	$('a.lightbox').fancybox({
		titleShow: false
	});
	// map show button with lightbox
	$('a.mapLightbox').fancybox({
		onStart: function() {
			if (typeof(document.largeMap) !== 'undefined') {
				var map = document.largeMap;
				var center = map.getCenter();
				var offset = 0.01;
				var newCenter = new GLatLng(center.lat() + 0.012, center.lng() - 0.022);
				map.checkResize();
				map.setCenter(newCenter);
			}
		},
		onComplete: function() {
			if (typeof(document.largeMap) !== 'undefined') document.largeMap.checkResize();
		}
	});
	
	// gallery
	var slideShow = $('.slideShow').slideShow({
		interval: 10,
		slideSize: {
			width: 512,
			height: 384
		}
	});
	
	$.getScript(webroot + 'static/js/jquery.plugin.toggleValue.js', function() {
		$('#SearchForm input').toggleValue();
	});

	if ($('#LocationChooser').length > 0) {
		LocationChooser.initialize();
		LocationChooser.update();
	}
});