/* 
 * 
 * Map for "Eiendomsbasen"
 * An instance of this class is required for each map element
 * Each map instance is usually associated with a certain turnover (attribute: od_id)
 * 
 * Depends: ZoomController.js | Typecontroller.js | BobIcon.js | GoogleMap API
 * 
 * Andreas Rudi Søvik <andreas.rudi.sovik@eddamedia.no>
 * 
 */

var BobMap = new Class( {
	
	/*
	 * Constructor
	 * 
	 * coords - associative array {'lat'=>float, 'long'=>float}. map starting coordinates
	 * zoom - gmap zoom level
	 * type - gmap type
	 * container - id of dom element which map is to be attached to
	 * mode - "normal" or "mini". normal has standard zoom and type controllers, mini has none
	 * mapfeed - url to script which provides xml/json data for this map instance
	 * radius - of which to search for elements close to this element (od_id) - in meters
	 * startyear - year of earliest turnover to display
	 * endyear - year of latest turnover to display
	 * od_id - turnover id
	 * summaryboxes - boolean, output turnover data displayed on map to separate dom elements?
	 * 
	 */	
	initialize: function(coords, zoom, type, container, mode, mapfeed, radius, startyear, endyear, od_id, summaryboxes) {
		this.coords = coords;
		this.zoom = zoom;
		this.type = type;
		this.container = container;
		this.mode = mode;
		this.mapfeed = mapfeed;
		this.radius = radius;
		this.od_id = od_id;
		
		// marker buffers
		this.t_markers_array = [];
		this.tinde_markers_array = [];

		// marker clusters
		this.cluster = null;
		this.tinde_cluster = null;
		
		// filters
		this.type_filter = null;
		this.price_filter = null;
		this.startyear = startyear;
		this.endyear = endyear;
		
		// summary boxes output flag		
		if (summaryboxes == null) this.summaryboxes = false; 
		else this.summaryboxes = true;
	},

	/*
	 * Create gmap instance and attach to dom
	 * Only controller attachments separate the map types
	 */	
	attachMap: function() {
		if (GBrowserIsCompatible()) {
        	this.map = new GMap2($(this.container));	
			this.map.setCenter(new GLatLng(this.coords["lat"], this.coords["long"]), this.zoom, this.type);
			
			switch(this.mode) {
				case "normal":{
					this.map.addControl(new ZoomController(this.map));
					this.map.addControl(new TypeController(this.map));
					break;
				}
				
				case "mini": 
					break;
			}
			
			this.mapstatus = new Element('div',{'class':'mapload'});
			new Element('img', {'src':'/eiendomsbasen/html/assets/graphics/ajax-loader.gif'}).injectInside(this.mapstatus);
			this.mapstatus.injectInside(this.container);
		}		
	},
	
	/*
	 * Turnover Cluster click event
	 * args - native parameter for clusterMarker click event
	 * obj - parent class of map
	 * 
	 * Requests address information about the clustered turnovers and displays it in a popup on map
	 */
	clusterClick: function(args, obj) {
		
		if (args.clusteredMarkers[0].street != null) {
			
            var output = 
			'<div class="twocol">' +
           		'<div class="newsitem left">' +
            		'<div style="width:23em; height:13em; overflow:auto;">';
			            for (var i = 0; i < args.clusteredMarkers.length; i++) {
			                if (args.clusteredMarkers[i].type == 'U') 
			                    args.clusteredMarkers[i].type = 'AN';
			                output += '<div class="clearfix"><img style="float:left;" src="/eiendomsbasen/html/assets/graphics/map/' + args.clusteredMarkers[i].type + '_40x60.gif">';
			                output += '<p style="line-height:43px;font-size:16px;margin-top:4px;margin-left:4px;"><b><a href="turnover?id=' + args.clusteredMarkers[i].id + '">' + args.clusteredMarkers[i].street + " " + args.clusteredMarkers[i].housenumber + " </a></b></p></div>";
			            }
            		output += '</div>' +
            	'</div>' +
            '</div>';	
			
			args.clusterMarker.openInfoWindowHtml(output);
			
		} else {
		
			var turnoversRequest = new Request({
				url: obj.mapfeed + 'mapturnovers',
				method: 'get',
				
				onSuccess: function(responseText, responseXML){
					var xml = GXml.parse(responseText);
					
					var properties = xml.documentElement.getElementsByTagName("property");
					var id = xml.documentElement.getElementsByTagName("id");
					var street = xml.documentElement.getElementsByTagName("street");
					var housenumber = xml.documentElement.getElementsByTagName("housenumber");
					var type = xml.documentElement.getElementsByTagName("type");
					
					var output = '<div class="twocol">' +
					'<div class="newsitem left">' +
					'<div style="width:23em; height:13em; overflow:auto;">';
					for (var i = 0; i < properties.length; i++) {
						if (type[i].firstChild.data == 'U') 
							type[i].firstChild.data = 'AN';
						output += '<div class="clearfix"><img style="float:left;" src="/eiendomsbasen/html/assets/graphics/map/' + type[i].firstChild.data + '_40x60.gif">';
						output += '<p style="line-height:43px;font-size:16px;margin-top:4px;margin-left:4px;"><b><a href="turnover?id=' + id[i].firstChild.data + '">' + street[i].firstChild.data + " " + housenumber[i].firstChild.data + " </a></b></p></div>";
					}
					output += '</div>' +
					'</div>' +
					'</div>';
					
					args.clusterMarker.openInfoWindowHtml(output);
				}
				
			});
			
			// push turnover id's in the clicked cluster into an array
			ids = [];
			for (var i = 0; i < args.clusteredMarkers.length; i++) {
				ids.push(args.clusteredMarkers[i].id);
			}
			
			// request detailed turnover details from server
			turnoversRequest.send('id=' + escape(ids.join(',')));
			
		}
	}, 
	
	/*
	 * Tinde cluster click event
	 * args - native parameter for clusterMarker click event
	 * obj - parent class of map
	 * 
	 * Properties for sale on tinde.no may also overlap
	 */
	tindeClusterClick: function(args, obj) {
	},


	/*
	 * Display infowindow on map with information on selected turnover
	 * id - turnover id
	 * point - GLatLng, where to display information bubble
	 */
	displayTurnoverData: function(marker, point) {
		obj = this.map;
		
		if (marker.street != null) {
            var output = '<div class="twocol">' +
            				'<div class="newsitem left">' +
          					  '<div style="height:10em; overflow:auto;">' +
          						  '<h3 style="font-size:18px;"><a href="turnover?id=' + marker.id + '">' + marker.street + " " + marker.housenumber + "</a></h3>" +
           							'<p style="margin-top:8px;"><b>Solgt for kr. <span class="price">' + marker.price + '</span></b></p>' + '<a href="turnover?id=' + marker.id +'">Gå til overdragelse</a>' +
            					'</div>' +
           					 '</div>' +
            				'</div>';
            
            obj.openInfoWindowHtml(point, output);	
		
		} else {

			var turnoverRequest = new Request({
				url: this.mapfeed + 'mapturnovers',
				method: 'get',
				onSuccess: function(responseText, responseXML){
					var xml = GXml.parse(responseText);
					
					var properties = xml.documentElement.getElementsByTagName("property");
					
					var id = xml.documentElement.getElementsByTagName("id");
					var street = xml.documentElement.getElementsByTagName("street");
					var type = xml.documentElement.getElementsByTagName("type");
					var housenumber = xml.documentElement.getElementsByTagName("housenumber");
					var price = xml.documentElement.getElementsByTagName("price");
					
					var output = '<div class="twocol">' +
									'<div class="newsitem left">' +
										'<div style="height:10em; overflow:auto;">' +
											'<h3 style="font-size:18px;"><a href="turnover?id=' + id[0].firstChild.data +'">' + street[0].firstChild.data + " " + housenumber[0].firstChild.data + "</a></h3>" +
												'<p style="margin-top:8px;"><b>Solgt for kr. <span class="price">' + price[0].firstChild.data + '</span></b></p>' +
												'<a href="turnover?id=' + id[0].firstChild.data +'">Gå til overdragelse</a>' +
										'</div>' +
									'</div>' +
								'</div>';
					
					obj.openInfoWindowHtml(point, output);
				}
				
			});
			
			turnoverRequest.send('id=' + marker.id);
			
		}	
	},

	/*
	 * Display infowindow on map with information on selected property from tinde.no
	 * id - turnover id
	 * point - GLatLng, where to display information bubble
	 */	
	displayTindeData: function(id, point) {
		
		obj = this.map;
		
		var tindeRequest = new Request({
			url: this.mapfeed + 'maptindeinfo',
			method: 'get',
			onSuccess: function(responseText, responseXML) 
			{
				var xml = GXml.parse(responseText);
					
				var properties = xml.documentElement.getElementsByTagName("property");
				var id = xml.documentElement.getElementsByTagName("id");
				var title = xml.documentElement.getElementsByTagName("title");
				var address = xml.documentElement.getElementsByTagName("address");
				var area = xml.documentElement.getElementsByTagName("area");
				var type = xml.documentElement.getElementsByTagName("type");
				var price = xml.documentElement.getElementsByTagName("price");
				
				var output = '<div class="twocol">' +
								'<div class="newsitem left">' +
									'<div style="width:25em;height:14em;overflow:auto;">';
							
										output += '<h3 style="font-size:18px;"><a href="http://tinde.no/eiendom/' + id[0].firstChild.data + '" target="_blank">' + address[0].firstChild.data + '</a></h3>';
										if (title[0].firstChild != null) output += '<p style="margin-top:8px;">' + title[0].firstChild.data + '</p>'
										if (type[0].firstChild != null) output += '<p style="margin-top:8px;"><b>Type:</b> ' + type[0].firstChild.data + '</p>';
										if (area[0].firstChild != null) output += '<p style="margin-top:8px;"><b>Areal:</b> ' + area[0].firstChild.data + ' m&sup2;</p>';
										if (price[0].firstChild != null) output += '<p style="margin-top:8px;"><b>Prisantydning:</b><span class="price"> ' + price[0].firstChild.data + '</span></p>';
										
										output += '<p style="margin-top:8px;"><a href="http://tinde.no/eiendom/' + id[0].firstChild.data + '" target="_blank">Gå til annonse på tinde.no' + '</a></p>' +
							 		'</div>'+
								'</div>' + 
							'</div>';
							
				obj.openInfoWindowHtml(point, output);
			}
			
		});
		
		tindeRequest.send('ref=' + id);			
	},

	/*
	 * Parse turnover coordinate data for plotting on googlemap
	 */
	parseXML: function(url, feedaction) 
	{
		var obj = this;
		var mp = this.map;

		if (obj.summaryboxes) {
			var boxes = ['AN', 'BL', 'FB', 'RK', 'TB', 'UB'];
			for (var i = 0; i < boxes.length; i++)
				$(boxes[i]).set('html', '');
		}	
		
		var mapRequest = new Request({
			url: this.mapfeed + feedaction,
			method: 'get',
			onRequest: function()
			{
				obj.showLoadStatus();
			},
			onComplete:function()
			{
				obj.hideLoadStatus();
			},
			onSuccess: function(responseText, responseXML) 
			{
				var xml = GXml.parse(responseText);
					
				var properties = xml.documentElement.getElementsByTagName("property");
				var id = xml.documentElement.getElementsByTagName("id");
				var type = xml.documentElement.getElementsByTagName("type");
				var street = xml.documentElement.getElementsByTagName("street");
				var housenumber = xml.documentElement.getElementsByTagName("housenumber");
				var price = xml.documentElement.getElementsByTagName("price");
				var lat = xml.documentElement.getElementsByTagName("lat");
				var ltd = xml.documentElement.getElementsByTagName("long");
				var error = xml.documentElement.getElementsByTagName("error");
				
				if (error[0]) {
					 mp.openInfoWindowHtml(new GLatLng(obj.coords["lat"], obj.coords["long"]), '<div style="color:red;font-size:18px;font-weight:bold;width:250px;">' + error[0].firstChild.data + '</div>');	
				}
					
				for (var i = 0; i < properties.length; i++) {
					var point = new GLatLng(parseFloat(lat[i].firstChild.data), parseFloat(ltd[i].firstChild.data));
					var marker = new BobMarker(point, id[i].firstChild.data, type[i].firstChild.data, street[i].firstChild.data, housenumber[i].firstChild.data, price[i].firstChild.data, type[i].firstChild.data, obj);
					
					obj.t_markers_array.push(marker);
					
					if (obj.summaryboxes)
						obj.loadSummaryBox(marker);
					
				}
				
				if (obj.cluster != null)
					obj.cluster.removeMarkers();
				
				if(obj.t_markers_array.length != 0) {
					obj.cluster = new ClusterMarker(obj.map, {
						
						markers: obj.t_markers_array,
						clusterMarkerClick: function(arg) {
							obj.clusterClick(arg, obj);
						}
					
					});
					obj.cluster.refresh();
				}	
			}
		});
		
		mapRequest.send(url);
	},
	
	/*
	 * Plot an individual turnover on map
	 */
	plotTurnoverPoint: function () {
		this.parseXML("id=" + this.od_id, 'mapturnover');
	},
	
	/*
	 * Plot several turnovers on map and external summary information boxes if this particular map instance requires it
	 */
	plotTurnoverPoints: function() {
		this.t_markers_array = [];
		this.map.clearOverlays();
		
		var request = "center=" + this.coords['lat'] + "," + this.coords['long'];
		
		// filters
		if (this.radius != null && this.radius != 0)
			request = request + "&radius=" + this.radius;
		
		if (this.area != null) 
			request = request + "&area=" + escape(this.area);
			
		if (this.postarea != null)
			request = request + "&postarea=" + escape(this.postarea);
			
		if (this.startyear != null && this.endyear != null)
			request = request + "&years=" + this.startyear + ',' + this.endyear;	
			
		if (this.type_filter != null && this.type_filter != 'A')	
			request = request + "&type=" + this.type_filter;	
		
		if (this.price_filter != null && this.price_filter != 'A')
			request = request + "&price=" + this.price_filter;	
		
		this.parseXML(request, 'mapradius');
	},
	
	/*
	 * Plot data from tinde.no on the map
	 */
	plotTindePoints: function() {
		this.tinde_markers_array = [];
		
		var request = "radius=" + this.radius + "&center=" + this.coords['lat'] + "," + this.coords['long'];
		var obj = this;
		
		var tindeRequest  = new Request({
			url: this.mapfeed + 'maptinde',
			method: 'get',
			onSuccess: function(responseText, responseXML) 
			{
				var xml = GXml.parse(responseText);
					
				var properties = xml.documentElement.getElementsByTagName("property");
				var id = xml.documentElement.getElementsByTagName("id");
				var lat = xml.documentElement.getElementsByTagName("lat");
				var ltd = xml.documentElement.getElementsByTagName("long");		
				
				for (var i = 0; i < properties.length; i++) {
					var point = new GLatLng(parseFloat(lat[i].firstChild.data), parseFloat(ltd[i].firstChild.data));
					var marker = new BobMarker(point, id[i].firstChild.data, 'TI', '', '', '', 'TI', obj);
					
					obj.tinde_markers_array.push(marker);
				}
				
				if (properties.length > 0) {
					if (obj.tinde_cluster != null && obj.tinde_markers_array != []) 
						obj.tinde_cluster.removeMarkers();
					
					if (obj.tinde_markers_array != []) {
						obj.tinde_cluster = new ClusterMarker(obj.map, {
							markers: obj.tinde_markers_array,
							tindeClusterMarkerClick: function(arg){
								obj.tindeClusterClick(arg, obj);
							}
						});
						
						obj.tinde_cluster.refresh();
					}
				}
			}
		});
		
		tindeRequest.send(request);
	},
	
	/*
	 * Load turnover summaries into the appropriate dom elements
	 */
	loadSummaryBox: function(marker) {
		
		if (marker.street != null) {

			var output = '<a href="turnover?id=' + marker.id + '">' + marker.street + ' ' + marker.housenumber + '</a> - ' + marker.price + '<br>';
			
			if (marker.type == 'U') 
				marker.type = 'AN';
			
			if ($(marker.type)) $(marker.type).appendHTML(output);
					
		} else {
			var request = new Request({
				url: this.mapfeed + 'mapradius',
				method: 'get',
				onSuccess: function(responseText, responseXML){
					if (responseText != '') 
						if (marker.type == 'U') {
							marker.type = 'AN';
							$(marker.type).set('html', $(marker.type).get('html') + responseText);
						}
						else 
							$(marker.type).set('html', responseText);
					else 
						if (type != 'U') 
							$(marker.type).set('html', 'Ingen overdragelser.');
				}
			});
			
			// basic request string
			var requests = 'radius=' + this.radius + '&center=' + this.coords['lat'] + "," + this.coords['long'] + "&databox=" + type;
			
			// filters
			if (this.area != null) 
				requests = requests + '&area=' + escape(this.area);
			
			if (this.postarea != null) 
				requests = requests + "&postarea=" + escape(this.postarea);
			
			if (this.startyear != null && this.endyear != null) 
				requests = requests + "&years=" + this.startyear + ',' + this.endyear;
			
			if (this.type_filter != null && this.type_filter != 'A') 
				requests = requests + "&type=" + this.type_filter;
			
			if (this.price_filter != null && this.price_filter != 'A') 
				requests = requests + "&price=" + this.price_filter;
			
			request.send(requests);
		}
	},
	
	/*
	 * Find location on map
	 * loc - string describing a geographic location
	 */
	findLocation: function(loc) {
		obj = this;
		obj.area = loc;

		geocoder = new GClientGeocoder();
		geocoder.getLatLng(loc + ', Norway', function(point){
			obj.foundLocation(point, obj);
		});
	},
	
	/*
	 * When a location is found, this method navigates the map to coordinates of found location and plots turnovers
	 * point - GLatLng of found location
	 * obj - current instance of BobMap
	 */
	foundLocation: function(point, obj) {
		obj.coords['lat'] = point.lat();
		obj.coords['long'] = point.lng();
		
		obj.plotTurnoverPoints();
		obj.map.setCenter(point, obj.zoom, obj.type);
	},
	
	showLoadStatus: function() {
		this.mapstatus.setStyle('display', 'block');
	},
	
	hideLoadStatus: function() {
		this.mapstatus.setStyle('display', 'none');
	},
	
	/*
	 * Draw a circle marker on map (used for outlining the active search radius)
	 * Currently not used
	 */
	drawCircle: function(center, radiusMeters, color, thickness, opacity, fillColor, fillOpacity) {
        var degreesPerPoint = 3;
		var mPl = 111120.000190848;
        var radiusLat = radiusMeters * (1 / mPl);
        var radiusLon = radiusMeters * (1 / (mPl * Math.cos(parseFloat(center.lat()) * Math.PI / 180)));
        var points = new Array();
		
        for (var i = 0; i < 360; i += degreesPerPoint) {
            var point = new GLatLng(parseFloat(center.lat()) + (radiusLat * Math.sin(i * Math.PI / 180)), parseFloat(center.lng()) + (radiusLon * Math.cos(i * Math.PI / 180)));

            points.push(point);
        }
		
        points.push(points[0]);
        
        markerCircle = new GPolygon(points, color, thickness, opacity, fillColor, fillOpacity)
        this.map.addOverlay(markerCircle);
    }
	
} );

