/**
 * @author Ed Slocombe 
 */

var VET_MAP_UK = { toString : function () { return "UK"; },
					 zoom : 5,
					 sw_lat : 46.61926103617151,
					 sw_lng : -27.509765625,
					 ne_lat : 61.81466389468391,
					 ne_lng : 16.435546875
				   }; 
var VET_MAP_US = { toString : function () { return "US"; },
					 zoom : 3,
					 sw_lat : 9.622414142924805,
					 sw_lng : -134.82421875,
					 ne_lat : 52.802761415419674,
					 ne_lng : -46.93359375
				   }; 

var VetMap = {
 	
	OUT_OF_BOUNDS_ERROR : "Point out of bounds",
	
	locale : null,
	map : null,
	geocoder : null,
	container : null,
	mapBounds : null,
	callback : null,
	addMarkerEnabled : true,
	
	/**
	 * Initalise map, in the container with the size of the container.
	 * Should be called on load.
	 * 
	 * @var int containerId    				=> ID of div holding map (will ensure container
	 * 						     			   is visible if not when function called) 
	 * [@var function markerPlaceCallback]  => Callback function that is called when a 
	 * 										   marker is placed
	 * [@var string locale]    				=> Specifies bounds of GoogleMap (limits zoom 
	 * 						      			   to country)
	 * [@var object options]   				=> All boolean (all must be set or nothing passed):
	 * 										 	 movement => Enables movement control
	 * 							  				 mapType  => Enables map, satellite, .. switches
	 * 							  				 zoom	 => Enables movement control 
	 * @return boolean sucess  				=> Whether map could be initialised   
	 */
	init : function (containerId, markerPlaceCallback, locale, options) {
		
		this.container = document.getElementById(containerId);
		if (markerPlaceCallback) this.callback = markerPlaceCallback;
		this.locale = (locale)? locale : VET_MAP_UK;
		
		if (! GBrowserIsCompatible()) return false;
		
		this.map = new GMap2(this.container);

		// Add control
		this.map.addControl(new GSmallMapControl());

		// Set bounds of map
		var sw = new GLatLng(this.locale.sw_lat, this.locale.sw_lng);
		var ne = new GLatLng(this.locale.ne_lat, this.locale.ne_lng);
		this.mapBounds = new GLatLngBounds(sw, ne);
			
		if (this.addMarkerEnabled) GEvent.addListener(this.map,"click", function(overlay, latlng) { VetMap.moveMarker(overlay, latlng); });
		
        if (options) {
			if (options.movement) 
				this.map.addControl(new GSmallMapControl());
			if (options.mapType) 
				this.map.addControl(new GMapTypeControl());
			if (options.zoom) 
				this.map.enableScrollWheelZoom();
		} else this.map.enableScrollWheelZoom();
		
		return true;
			
	},
	
	/**
	 * Sets centre of map to start with. If initAddress
	 * is unspecified, map is centred on map's bounds.
	 * 
	 * [@var ? arg1]   			 => Address with which to centre map 
	 * 						        OR
	 * 						        If arg2 is present, the latitude 
	 * 						        to centre map at
	 * [@var int arg2]			 => If arg1 present, the longditude 
	 * 						        to centre map at
	 * [@var boolean addMarker]  => Only for use with lat lng, doesn't 
	 * 								place marker if set to false
	 */
	open : function (arg1, arg2, addMarker) {
		
		if (arg1 && !arg2) {
			// Centre at address
			this.centreOnAddress(arg1);
		} else if (arg1 && arg2) {
			// Centre at lat lng
			var latlng = new GLatLng(arg1, arg2);
			this.centreOnLatLng(new GLatLng(arg1, arg2));
			if (addMarker !== false) this.moveMarker(null, latlng);
		} else {
			// Centre around bounds of country
			var zoom = (this.locale == VET_MAP_UK)? VET_MAP_UK.zoom : VET_MAP_US.zoom;
			this.map.setCenter(this.mapBounds.getCenter(), zoom);
		}


	}, 
	
	/**
	 * Move (or add) the marker to the latlng coords.
	 * Called by onClick handler but can be called manually.
	 * Calls callback function if defined
	 * 
	 * [@var Object overlay]   => Overlay of map  
	 * @var String latlng      => Latitude and longditude to position marker at
	 * @return boolean sucess  => Whether marker be moved   
	 */
	moveMarker : function (overlay, latlng) {
				
		if (! latlng) return false;		
		if (!VetMap.mapBounds.containsLatLng(latlng)) {
			if (this.callback) {
				this.callback(this.OUT_OF_BOUNDS_ERROR);
				return;
			} 
			else throw new Error(this.OUT_OF_BOUNDS_ERROR);
		}
		this.map.clearOverlays();
		this.map.addOverlay(new GMarker(latlng));
		if (this.callback) this.callback(latlng.lat(), latlng.lng());
		return true;

	},	
	
	placeMarker : function (lat, lng, practiceHTML, openInfo) {
		var latLng = new GLatLng(lat, lng);
		var gMarker = new GMarker(latLng);
		this.map.addOverlay(gMarker);		
		if (practiceHTML) {
			gMarker.bindInfoWindowHtml(practiceHTML);
			if (openInfo === true) {
				gMarker.openInfoWindowHtml(practiceHTML);
				this.centreOnLatLng(latLng, 10);
			}
		}
	},
	
	placeVWMarker : function (lat, lng, practiceHTML, openInfo) {
		var latLng = new GLatLng(lat, lng);
		var gMarker = new GMarker(latLng);
		this.map.addOverlay(gMarker);		
		if (practiceHTML) {
			gMarker.bindInfoWindowHtml(practiceHTML);
		}
	},
	setVWzoom : function () {
		this.map.setCenter(new GLatLng(54.478052,-4), 6);

	},
	clearMarkers : function() {
		this.map.clearOverlays();
	},
	
	/**
	 * Centres map around address / postcode, not very accurate.
	 * Ideally use to centre on a town or city, but no further.
	 * 
	 * @var string address   => Address with which to centre map 
	 */
	centreOnAddress : function (address, zoom) {
		this.geocoder = new GClientGeocoder();
		if (!zoom) zoom = (this.locale == VET_MAP_UK)? VET_MAP_UK.zoom : VET_MAP_US.zoom;
		this.geocoder.getLatLng(address, function(point) { 
			if (point && VetMap.mapBounds.containsLatLng(point)) 
				VetMap.map.setCenter(point, zoom); 
			else VetMap.map.setCenter(VetMap.mapBounds.getCenter(), zoom);
		} );
	},
	
	/** 
	 * Centres map around latidude and longditude coordinates.
	 * Coordinates normally attained from DB.
	 * 
	 * @var string latLng   => Coordinate with which to centre map 
	 */
	centreOnLatLng : function (latLng, zoom) {
		if (!zoom) zoom = 12;
		this.map.setCenter(latLng, zoom);
	}
	
}

