/**
 * @author Johan
 */
 
/**
 * Google Maps API Interface
 * @param {Object} element
 */
var Map = Class.create({

	element: null,
	map: null,

	// polygons
	polygons: $A(),
	// drawn polygon
	drawn_polygons: $A(),
	
	// Default polygon style
	polygonStyle: $H({
		borderColor: '#000',
		borderWidth: 2,
		borderOpacity: 0.5,
		backgroundColor: '#60a6fd',
		backgroundOpacity: 0.2
	}),

	// markers
	markers: $A(),

	// center (GLatLng)
	center: null,
	// zoom level (int)
	zoom: 10,

	/**
	 * Initialize the map
	 * @param {Object} element
	 */
	initialize: function(element) {
		
		this.element = element;
		
		// browser compatible?
		if(!GBrowserIsCompatible()) {
			alert('Uw browser is niet compatible met Google Maps.');
			return false;
		}
	
		// parse all data in the map element
		this.parseData();
	
		// load/apply the map
		this.map = new GMap2(this.element);
		this.map.addControl(new GSmallZoomControl());
		this.map.addControl(new GOverviewMapControl());
		this.map.addControl(new GMapTypeControl());
		this.setCenter(this.center, this.zoom);
	
		//this.element.select('svg').invoke('remove');
	
		// apply all data found in the element like poly's and markers.
		this.applyData();
		
		// save the position:
		// we can use this.returnToSavedPosition() to go back to the start.
		this.map.savePosition();
		// nasty:
		this.element.select('a, span').invoke('hide');
		setRastersOnMap();
	},

	parseData: function() {
		// check for polygons
		this.element.select('ul.polygon').each(function(ul) {
			this.addPolygon(ul);
		}.bind(this));

		// check for markers
		this.element.select('ul.markers li').each(function(li) {
			this.addMarker(li);
		}.bind(this));

		// check for center parameter
		this.center = new GLatLng(51.704683,4.516754); //5
		if( (centerData = this.element.down('p.center') ) ) {
			latlong = centerData.innerHTML.split(',');
			this.center = new GLatLng(latlong[0], latlong[1]);
			this.updatedCenter = true;
		}

		if ((zoomData = this.element.down('p.zoom'))) {
			this.zoom = zoomData.innerHTML;
		}
	},

	applyData: function() {
	
		this.clearOverlays();
	
		// draw polygons:
		if(this.polygons.size() > 0) {
			this.polygons.each(function(points) {
				this.drawPolygon(points);
			}.bind(this));
		}
		
		// draw markers:
		if(this.markers.size() > 0) {
			this.markers.each(function(marker) {
				this.map.addOverlay(marker);
			}.bind(this));
		}
		
		// find center automagicly:
		if(!this.updatedCenter && this.drawn_polygons.size() > 0) {
			var mapbounds = false;//this.map.getBounds();
			this.drawn_polygons.each(function(polygon) {
				var polybounds = polygon.getBounds();
				// we start expanding the bounds of the first poly we find
				// when all poly's fit in these bounds we center and zoom
				// the map to these bounds.
				if(!mapbounds) {
					mapbounds = polybounds;
				}
				if(!mapbounds.containsBounds(polybounds)) {
					mapbounds.extend(polybounds.getSouthWest());
					mapbounds.extend(polybounds.getNorthEast());
				}
			});
			
			this.map.setCenter(mapbounds.getCenter());
			this.map.setZoom(this.map.getBoundsZoomLevel(mapbounds));

		} else {
			// center is fixed by the <p class="center" /> element
		}
	},

	/**
	 * Click event
	 */
	click: function(overlay, latlng) {
		//var divXY = this.map.fromLatLngToDivPixel(latlng);
		this.map.addOverlay(new GMarker(latlng));
	},

	/**
	 * Marker functions
	 * ----------------
	 * 
	 * Add a marker
	 */
	addMarker: function(li) {
		if((span = li.down('span'))) {
			var text = span.innerHTML;
			span.remove();
		}
		var latlong = li.innerHTML.split(',');
		var point = new GLatLng(latlong[0],latlong[1]);
		
		var icon = new GIcon(G_DEFAULT_ICON);

		switch(li.className) {
			case 'ave':
				icon.image = BaseURL+'/img/map-markers/map-logo-marker-ave.png';
				icon.shadow = '';
				icon.iconSize = new GSize(42, 40);
				icon.iconAnchor = new GPoint(21, 40);
			break;

			case 'rehorst':
				icon.image = BaseURL+'/img/map-markers/map-logo-marker-rehorst.png';
				icon.shadow = '';
				icon.iconSize = new GSize(42, 40);
				icon.iconAnchor = new GPoint(21, 40);
			break;
		}
		
		var marker = new GMarker(point, icon);
		if(text) {
			GEvent.addListener(marker,"click", function() {
				this.map.openInfoWindowHtml(point, text);
			}.bind(this));	
		}
		
		this.markers.push(marker);
	},

	/**
	 * Custom marker
	 * @param {Object} ul
	 */
	getIcon: function(color) {
		if(!color)
			color = 'orange';

		var icon = new GIcon();
		icon.image = BaseURL+'/img/map-markers/mm_20_'+color+'.png';
		icon.shadow = BaseURL+'/img/map-markers/mm_20_shadow.png';
		icon.iconSize = new GSize(12, 20);
		icon.shadowSize = new GSize(22, 20);
		icon.iconAnchor = new GPoint(6, 20);
		icon.infoWindowAnchor = new GPoint(5, 1);
		return icon;
	},

	/**
	 * Polygon functions
	 * -----------------
	 * 
	 * Add a polygon
	 */
	addPolygon: function(ul) {
		var points = $A();
		ul.select('li').each(function(li, index) {
			points.push(li.innerHTML.split(','));
		}.bind(this));
		
		for(var i=0; i<points.size(); i++) {
			points[i] = new GLatLng(points[i][0],points[i][1]);
		}

		// check if the polygon is closed. if not, close it.
		if(points.first().equals(points.last())) {
			points.push(points.first());
		}

		var polygon = this.polygonStyle.merge($H({ 
			points: points,
			borderColor: '#F00'
			// todo: get more style from style tag
		}));
		this.polygons.push(polygon);
	},

	/**
	 * Draw a polygon
	 * @param {Object} polygon
	 */
	drawPolygon: function(polygon) {
		var polygon = new GPolygon(
			polygon.get('points'),
			polygon.get('borderColor'),
			polygon.get('borderWidth'),
			polygon.get('borderOpacity'),
			polygon.get('backgroundColor'),
			polygon.get('backgroundOpacity')
		);
		this.map.addOverlay(polygon);
		this.drawn_polygons.push(polygon);
	},

	/**
	 * Center the map on the given polygon
	 * @param {Object} polygon
	 */
	centerPolygon: function(polygon) {
		
	},

	/**
	 * Centers the map
	 * @param {Long} lat
	 * @param {Long} long
	 * @param {Int} zoom
	 */
	setCenter: function(centerPoint, zoom) {
		this.map.setCenter(centerPoint, parseFloat(zoom));
	},

	/**
	 * Clears all overlays on the map 
	 */
	clearOverlays: function() {
		this.map.clearOverlays();
	},

	/**
	 * Returns to the saved position
	 * This saved position is set when the map is fully loaded.
	 */
	returnToSavedPosition: function() {
		this.map.returnToSavedPosition();
	}

});


var AdminMap = Class.create(Map, {
	// precision of points on the map:
	latlng_precision: 7,

	polygonPoints: $A(),

	centerInput: null,

	initialize: function($super, element) {
		$super(element);
		
		// center input:
		this.centerInput = new Element('input', { 'type': 'hidden', name: 'center', value: this.map.getCenter().toUrlValue(this.latlng_precision) });
		$('polygonPoints').appendChild(this.centerInput);
		// zoom input:
		this.zoomInput = new Element('input', { 'type': 'hidden', name: 'zoom', value: this.map.getZoom() });
		$('polygonPoints').appendChild(this.zoomInput);
		
		GEvent.addListener(this.map, "moveend", function() {
        	this.centerInput.value = this.map.getCenter().toUrlValue(this.latlng_precision);
			this.zoomInput.value = this.map.getZoom();
        }.bind(this));
		
		if((button = $('save-polygon')))
			button.observe('click', this.savePolygon.bind(this));
		if((button = $('clear-overlays')))
			button.observe('click', this.clearOverlays.wrap(function(proceed, event) {
				event.stop(); // stop the event
				this.polygonPoints = $A();
				$('polygonPoints').select('input.area').invoke('remove');
				proceed(); // call this.clearOverlays()
			}).bind(this));
	},

	// apply admin specific data:
	applyData: function($super) {
		// apply other data:
		$super();
		// add the click event:
		var clickEvent = GEvent.bind(this.map, 'click', this, this.click);
	},

	// admin click event:
	click: function($super, overlay, latlng) {
		//var divXY = this.map.fromLatLngToDivPixel(latlng);
		$('save-polygon').enable();
		this.polygonPoints.push(latlng);
		this.map.addOverlay(new GMarker(latlng, this.getIcon('orange')));
	},

	savePolygon: function(event) {
		event.stop();
		// clear current overlays:
		this.clearOverlays();
		
		// close it:
		if(!this.polygonPoints.first().equals(this.polygonPoints.last())) {
			this.polygonPoints.push(this.polygonPoints.first());
		}

		// save it:
		$('polygonPoints').select('input.area').invoke('remove');
		this.polygonPoints.each(function(point) {
			var input = new Element('input', { 'type': 'hidden', name: 'area[]', className: 'area', value: point.toUrlValue(this.latlng_precision) });
			$('polygonPoints').appendChild(input);
		});
		
		// create it:
		var polygon = this.polygonStyle.merge($H({ 
			points: this.polygonPoints,
			borderColor: '#F00'
			// todo: get more style from style tag
		}));
		
		// draw it:
		this.drawPolygon(polygon);
	}

});

// todo: create method to convert rgb(#,#,#) notation to hex
Math.rgbToHex = function(r,g,b){
	return(r<<16 | g<<8 | b);
}

/**
 * The DOM Loaded event.
 * Fires when the DOM is fully loaded
 */
 
var map = '';
var forced = false;
 
function gmapini(name){
	map = new GMap2(document.getElementById(name));
	map.setCenter(new GLatLng(51.704683,4.516754), 10,G_HYBRID_MAP);
	map.addControl(new GSmallZoomControl());
	map.addControl(new GOverviewMapControl());
	map.addControl(new GMapTypeControl());
	var drawn_polygons = setRastersOnMap();	
	autoCenterAndZoom(drawn_polygons);
	//map.setZoom(5);
}

function forceCenterAndZoom(lon, lat, zoom){
	forced = true;
	map.setCenter(new GLatLng(lon,lat), zoom);
	map.setZoom(zoom);
}
 
function autoCenterAndZoom(drawn_polygons){
	if (!forced){
		var mapbounds = false;
		drawn_polygons.each(function(polygon) {
			var polybounds = polygon.getBounds();
			if(!mapbounds) {
				mapbounds = polybounds;
			}
			if(!mapbounds.containsBounds(polybounds)) {
				mapbounds.extend(polybounds.getSouthWest());
				mapbounds.extend(polybounds.getNorthEast());
			}
		});
				
		map.setCenter(mapbounds.getCenter());
		map.setZoom(map.getBoundsZoomLevel(mapbounds)-2);
	}
}
 
 /*
document.observe('dom:loaded', function() {
	$$('.map').each(function(element) {
		if(element.hasClassName('admin')) {
			new AdminMap(element);
		} else {
			var map = new GMap2(element);
			map.setCenter(new GLatLng(51.704683,4.516754), 10);
			map.addControl(new GSmallZoomControl());
			map.addControl(new GOverviewMapControl());
			map.addControl(new GMapTypeControl());
			//setPointsOnMap();
			setRastersOnMap(map);
		}
	});
});
Event.observe(window, 'unload', function(event){ GUnload() });
*/