﻿/**
 * jQuery.gsMap - A simple interface for the geosmart map.
 * Written by Michael Kerr (mike AT onlysport DOT co DOT nz)
 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
 * Date: 2009/11/02
 *
 * @author Michael Kerr
 * @version 0.3.1
 *
 **/

 (function($) {

	$.fn.gsMap = function( options )
	{
		if (! this.length) return false;

		var _map = $.data(this[0], 'gsMap');
		if (_map) { return _map; }

		_map = new $.gsMap( this[0], options );
		$.data(this[0], 'gsMap', _map);

		return _map;
	};

	$.fn.gsMapZoom = function( zoom )
	{
		this.each(function()
		{
			var self = $(this).gsMap();
			self.zoom( zoom );
		});
	};

	$.fn.gsListenLocate = function( selector, options )
	{
		this.each(function()
		{
			if (! options || ! options.file) return this;

			var self = $(this).gsMap();
			self.addListener(selector, 'change', function( event )
			{
				if (! event.data.map) return this;

				var mapObj = event.data.map;

				setTimeout(function()
				{

					var name = $(event.target).val().replace(' ', '-');
					while (/\s+/.test(name)) name = name.replace(' ', '-');

					$.get(options.file, { name: name }, function ( data )
					{
						var data = eval( '(' + data + ')' );

						if ( data.status == 'ERR' || ! data.location || ! parseInt(data.location.lgeocode_x) > 0 ) return this;

						var zoom = Math.abs(parseInt(11 * (data.location.llocation_level * (1 / 7))) - 11);

						mapObj.map.centerAndZoom(new GSPoint(data.location.lgeocode_x, data.location.lgeocode_y), zoom );
					});

				}, 100);
			});
		});
	};

	$.fn.gsMapUpdate = function()
	{
		this.each(function()
		{
			var self = $(this).gsMap();
			self.updateMapDisplay();
		});
	};

	$.fn.gsEnablePois = function( poi_class )
	{
		return this.each(function()
		{
			var self = $(this).gsMap();
			self.enablePois( poi_class );
		});
	};

	$.fn.gsAddFeature = function( title, geocode_x, geocode_y, focus, html, _draggable, _callback )
	{
		return this.each(function()
		{
			var self = $(this).gsMap();
			self.addFeature( title, geocode_x, geocode_y, focus, html, _draggable, _callback, false );
		});
	};

	$.gsMap = function( lmnt, options )
	{
		this.$lmnt = $(lmnt);
		this.opts = $.extend({}, $.gsMap.defaults, options);

		this.init();
	};

	$.extend($.gsMap,
	{
		version: '0.3.1',

		defaults:
		{
			map: null,

			title: '',
			info_html: '',

			geocode_x: 2530000,
			geocode_y: 5990000,
			zoom_level: 3,

			min_zoom: 0,
			max_zoom: 11,

			control_label: GSMap.MAP_CONTROL,

			hide_logo: false,

			drag_to_pan: true,
			centre_on_dbl_click: true,
			use_mouse_wheel_zoom: true,
			use_scale_bar: true,
			main_feature_draggable: false,

			dbl_click_zoom: false,

			interactive: true,
			use_main_feature: true,

			mapDblClicked: function ( theMap, point ) { if (this.dbl_click_zoom) theMap.zoom(theMap.getZoomLevel() - 1); theMap.centerAtCoordinate(point); },
			mapZoomed: function ( theMap, alpha, omega ) { if (omega < this.min_zoom || omega > this.max_zoom) { theMap.zoom(alpha); return false; }; },
			featureDragEnd: function ( feature ) { },

			features: null,
			listeners: null,

			_poi_proxy_url: '../js/proxy.php'
		},

		setDefaults: function( settings )
		{
			$.extend( $.gsMap.defaults, settings );
		},

		prototype:
		{
			init: function ()
			{
				var _map_params =
				{
					dragToPan: this.opts.interactive && this.opts.drag_to_pan,
					centerOnDblClick: !this.opts.dbl_click_zoom && this.opts.interactive && this.opts.centre_on_dbl_click,
					useMouseWheelZooming: this.opts.interactive && this.opts.use_mouse_wheel_zoom,
					useScalebar: this.opts.use_scale_bar,
					useLogo: !this.opts.hide_logo
				};

				this.opts.listeners = new Array();

				this.opts.features = new Array();
				this.opts.features[0] = 'RESERVED FOR THE MAIN FEATURE';

				this.map = new GSMap(this.$lmnt.attr('id'), _map_params);

				if (this.opts.interactive && this.opts.control_label) this.map.addControl( this.opts.control_label );

				if (this.opts.use_main_feature)
					this.addFeature( this.opts.title, this.opts.geocode_x, this.opts.geocode_y, true, this.opts.info_html, this.opts.main_feature_draggable, false);

				this.map.centerAtCoordinate(new GSPoint(this.opts.geocode_x, this.opts.geocode_y));
				this.zoom(this.opts.zoom_level);

				this.map.updateSize();

				this.map.addListener(this.opts);
			},

			zoom: function ( value )
			{
				this.map.zoom( value );
			},

			addFeature: function ( title, geocode_x, geocode_y, focus, html, _draggable, _callback, _is_main_feature )
			{
				var html = html || '';
				var focus = focus || false;
				var _is_main_feature = _is_main_feature || false;

				var xy = new GSPoint(geocode_x, geocode_y);
				var params = { 'name': title, 'coordinate': xy, 'infoHtml': html, 'draggable' : _draggable };

				var ind = _is_main_feature == true ? 0 : this.opts.features.length;

				this.opts.features[ind] = new GSPointFeature( params );

				var self = this;
				this.opts.features[ind].addEventHandler("click", function(e)
				{
					if (jQuery.trim(html) != '') this.showInfoWindow();
					if (typeof _callback == 'function')	_callback.call(self, this, e);
					GSUtil.cancelEvent(e);
				});

				this.opts.features[ind].addListener(this.opts);

				this.map.addFeature(this.opts.features[ind]);

				if (focus == true) this.map.centerAtCoordinate(new GSPoint(geocode_x, geocode_y));
			},

			updateMapDisplay: function() { this.map.updateSize(); },

			enablePois: function ( poi_class )
			{
				var self = this;

				if ( $( poi_class ).length <= 0 ) return false;

				$( poi_class ).click( function()
				{
					if (typeof _poi_mapping[$(this).val()] == 'undefined') return false;

					var category = _poi_mapping[$(this).val()];

					if ($(this).is(':checked') == true)
					{
						var params = self.poiBuildLayerQuery(category);

						if (params == false) return false;

						$.get(self.opts._poi_proxy_url, params, function ( data ) { self.poiDisplayLayer(data, self); });
					}
					else
					{
						var layer = self.map.getLayer(category);
						if (layer)
						{
							layer.clear();
						}
					}
				});
			},

			poiDisplayLayer: function ( data, self )
			{
				var data = eval( '(' + data + ')' );
				var category = self.poiGetCategoryFromQuery( data.pois.query );
				var layer = self.map.getLayer(category);
				if (layer == null) layer = self.map.createLayer(category);

				layer.addFeaturesJson(data.pois.poi, self.poiCreateFeature, category);
			},

			poiBuildLayerQuery: function ( category )
			{
				var mapCenter = this.map.getMapCenter();
				return 'category=' + category + '&x=' + mapCenter.x + '&y=' + mapCenter.y + '&radius=' + 10000 + '&sort=' + 'distance' + '&maxResults=' + 6;
			},

			poiGetCategoryFromQuery: function ( querystring )
			{
				var re = new RegExp(/category=([^&]+)/);
				return re.exec(querystring)[1];
			},

			poiCreateFeature: function ( feature, data, args )
			{
				if (args)
				{
					var icontype = args[0].toLowerCase();

					if (typeof iconCache != 'undefined' && typeof iconCache[icontype] != 'undefined')
					{
						var protoicon = iconCache[icontype];
						var icon = new GSIcon(protoicon);
						icon.alt = data.name;
						feature.setIcon(icon);
					}
				}

				var html = '<strong>' + data.name + '</strong><br/>';

				if (data.street) { html += data.street + '<br/>'; }
				html += data.suburb + ', ' + data.region + '<br/>';
				if (data.telephone) { html += data.telephone + '<br/>';	}

				feature.infoHtml = '<div style="width:180px;">' + html + '</div>';

				feature.addEventHandler("click", function(e)
				{
					this.showInfoWindow();
					GSUtil.cancelEvent(e);
				});
			},
			
			addListener: function( selector, method, _func )
			{
				if (_func && typeof _func == 'function')
				{
					var self = this;
					$(document).ready(function()
					{
						$(selector).bind(method, {map: self}, _func);
					});
				}
			},
			
			removeListener: function ( selector )
			{
			
			}
		}
	});

 })(jQuery);
