/**

TODO

- move map if marker is hidden by the info panel (gscreenpoint?)
- move branch-specific to seperate config (or ajax it)
- if first time and no matches, zoom to branch.
- branch marker onclick
- don't duplicate the icons by creating an array...
- check the area dropdown only includes available areas
- check within bounds follwing arrow pan
-click active icon to close

**/

var map;
var markers;
var markers_count = 0;
var active_marker = false;
var replaced_marker = false;
var replaced_marker_found = false;
var quick_html = false;
//var zoom_listener = false;
var move_listener = false;
var no_props_msg = 'Sorry, no properties were found. Please adjust your criteria or zoom out.';

// The allowed region which the whole map must be within
var allowedBounds = new GLatLngBounds(new GLatLng(49.5,-10), new GLatLng(59,3.6));

// The icons

var icons = [];

var iconLime = new GIcon(); 
iconLime.image = '/images/lpm/icon1.png';
iconLime.iconSize = new GSize(18, 18);
iconLime.iconAnchor = new GPoint(9, 9);
iconLime.infoWindowAnchor = new GPoint(9, 1);

var iconYellow = new GIcon(); 
iconYellow.image = '/images/lpm/icon2.png';
iconYellow.iconSize = new GSize(18, 18);
iconYellow.iconAnchor = new GPoint(9, 9);
iconYellow.infoWindowAnchor = new GPoint(9, 1);

var iconRed = new GIcon(); 
iconRed.image = '/images/lpm/icon3.png';
iconRed.iconSize = new GSize(18, 18);
iconRed.iconAnchor = new GPoint(9, 9);
iconRed.infoWindowAnchor = new GPoint(9, 1);

var iconPurple = new GIcon(); 
iconPurple.image = '/images/lpm/icon4.png';
iconPurple.iconSize = new GSize(18, 18);
iconPurple.iconAnchor = new GPoint(9, 9);
iconPurple.infoWindowAnchor = new GPoint(9, 1);

var iconTorquoise = new GIcon(); 
iconTorquoise.image = '/images/lpm/icon5.png';
iconTorquoise.iconSize = new GSize(18, 18);
iconTorquoise.iconAnchor = new GPoint(9, 9);
iconTorquoise.infoWindowAnchor = new GPoint(9, 1);

var iconGreen = new GIcon(); 
iconGreen.image = '/images/lpm/icon6.png';
iconGreen.iconSize = new GSize(18, 18);
iconGreen.iconAnchor = new GPoint(9, 9);
iconGreen.infoWindowAnchor = new GPoint(9, 1);

var iconBrown = new GIcon(); 
iconBrown.image = '/images/lpm/icon7.png';
iconBrown.iconSize = new GSize(18, 18);
iconBrown.iconAnchor = new GPoint(9, 9);
iconBrown.infoWindowAnchor = new GPoint(9, 1);

var iconGrey = new GIcon(); 
iconGrey.image = '/images/lpm/icon8.png';
iconGrey.iconSize = new GSize(18, 18);
iconGrey.iconAnchor = new GPoint(9, 9);
iconGrey.infoWindowAnchor = new GPoint(9, 1);

var iconBlue = new GIcon();
iconBlue.image = '/images/lpm/icon9.png';
iconBlue.iconSize = new GSize(18, 18);
iconBlue.iconAnchor = new GPoint(9, 9);
iconBlue.infoWindowAnchor = new GPoint(9, 1);

var iconGold = new GIcon();
iconGold.image = '/images/lpm/icon10.png';
iconGold.iconSize = new GSize(18, 18);
iconGold.iconAnchor = new GPoint(9, 9);
iconGold.infoWindowAnchor = new GPoint(9, 1);

// Whack them in an array where the key corresponds to our subtype ID
var customIcons = [];
customIcons[1]  = iconLime; 
customIcons[2]  = iconYellow;
customIcons[3]  = iconRed;
customIcons[4]  = iconPurple;
customIcons[5]  = iconTorquoise;
customIcons[6]  = iconGreen;
customIcons[7]  = iconBrown;
customIcons[8]  = iconGrey;
customIcons[9]  = iconBlue;
customIcons[10] = iconGold;

// Special cases
var iconMultipleCat = new GIcon(); 
iconMultipleCat.image = '/images/lpm/icon-multiple-cat.png';
iconMultipleCat.iconSize = new GSize(18, 18);
iconMultipleCat.iconAnchor = new GPoint(9, 9);
iconMultipleCat.infoWindowAnchor = new GPoint(9, 1);

var iconMultiple = new GIcon(); 
iconMultiple.image = '/images/lpm/icon-multiple.png';
iconMultiple.iconSize = new GSize(18, 18);
iconMultiple.iconAnchor = new GPoint(9, 9);
iconMultiple.infoWindowAnchor = new GPoint(9, 1);

var iconActive = new GIcon(); 
iconActive.image = '/images/lpm/icon-active2.gif';
iconActive.iconSize = new GSize(23, 23);
iconActive.iconAnchor = new GPoint(11, 11);
iconActive.infoWindowAnchor = new GPoint(11, 1);

var iconBranch = new GIcon(); 
iconBranch.image = '/images/lpm/icon-branch.png';
iconBranch.iconSize = new GSize(36, 30);
iconBranch.iconAnchor = new GPoint(18, 15);
iconBranch.infoWindowAnchor = new GPoint(18, 1);

var iconSold = new GIcon(); 
iconSold.image = '/images/lpm/icon8-sold.png';
iconSold.iconSize = new GSize(18, 18);
iconSold.iconAnchor = new GPoint(9, 9);
iconSold.infoWindowAnchor = new GPoint(9, 1);



function mapLoad() {

	if (!GBrowserIsCompatible()){
		alert ('Sorry, your browser is not compatible with the map.');
		return false;
	}
	
	map = new GMap2( $('#map')[0] );
	
	// ==== It is necessary to make a setCenter call of some description before adding markers ====
	// Basically this is the whole of the UK
	map.setCenter(new GLatLng(52.97603848323434, -1.3053131103515625), 5);
	
	// Set up the (one and only) active marker, but hide it
	active_marker = new GMarker(map.getCenter(), iconActive); 	// Can be anywhere really but centre it 
	GEvent.addListener(active_marker, 'click', function(){
		close_details();
	});
	active_marker.hide();										// Hide it until clicked
	
	var added = redrawMap(true, allowedBounds); // true denotes onload
	
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());
	
	// ====== Restricting the range of Zoom Levels =====
	// Get the list of map types      
	var mt = map.getMapTypes();
	// Overwrite the getMaximumResolution() method
	for (var i=0; i<mt.length; i++) {
		mt[i].getMinimumResolution = function() {return 5;}		// Prevents zooming out past a level where the whole of the UK is visible
		//mt[i].getMaximumResolution = function() {return 15;}
	}
	//==================================================
}	


function show_message(msg){
	$('#info').hide();
	$('#info').text(msg);
	$('#info').fadeIn(500);
}

// Called when the properties need loading or re-loading following drag
function redrawMap(first_time, starting_bounds){
	//console.log('redraw');
	
	if(first_time!=true) first_time = false;
	
	replaced_marker_found = false;
	
	if(!starting_bounds){
		var bounds	= map.getBounds();
	}
	else{
		var bounds	= starting_bounds;
	}
	
	var southWest	= bounds.getSouthWest();
	var northEast	= bounds.getNorthEast();
	
	checkBounds(); // Keeps view on UK	
	
	var data = {
		
		southwest_lng : southWest.lng(),
		northeast_lng : northEast.lng(),
		southwest_lat : southWest.lat(),
		northeast_lat : northEast.lat(), 
		buyrent:  $('input[name=buyrent]:checked').val() 
	
	}
	
	// Extract the min/max size if available
	if(sizes = $('select[name="size"] option:selected').val()) {
		sizes = sizes.split('-');
		$.extend(data, { minsize: sizes[0], maxsize: sizes[1] });
	}
	
	// Property types
	var types = [];

	for(var i=1;i<=10;i++){
		if($('input[name="type_'+ i +'"]:checked').val()) {
			types.push(i);
		}
	}
	
	// We require at least one type...
	if(types.length==0){
		show_message('At least one property type is required.');
		types.push(-1); // Assumes we won't ever have a type id of -1...
		map.clearOverlays();
		add_branches();
		return;
	}
	$.extend(data, { type: types.join(',') });
	
	// Area
	if(starting_bounds){
		if(area = $('select[name="location"] option:selected').val()) {
			$.extend(data, { location: area });
		}
	}
	
	// Keyword
	if(keyword = $('input[name="keyword"]').val()) {
		$.extend(data, { keyword: keyword });
	}
	
	//alert(datax);
	
	$.ajax({
		type: 'POST',
		url: '/mapxml',
		data: data,
		beforeSend: function(){
			$('#info').hide();
			$('#loading').show();
		},
		success: function(response){
			//alert(data);
			map.clearOverlays();
			
			// We already have an active marker so add it in in it's current visibility
			map.addOverlay(active_marker);	
						
			// Add the properties!
			var markers_count = addProperties(response, (!starting_bounds) ? false : true); // We autozoom if starting bounds have been provided
			
			////////// This bit allows the active marker to still show following a redraw ////////////////////////
			if(!first_time && replaced_marker && replaced_marker_found){	
				
				// Map has been reloaded and there has been a still-valid selection. However, by design, the replaced marker won't have been added by addProperties() so add it in now from global object (but hide it)
				map.addOverlay(replaced_marker);
				replaced_marker.hide();
				
			}
			else{
				
				// Map has been reloaded but there's been no selection so all properties will have been populated by addProperties() and we need to hide active marker
				active_marker.hide();
				close_details();
			}
			///////////////////////////////////////////////////////////////////////////////////////////////////////

			// Add branch(es)
			add_branches();
			
			// Set up listener so we do not reload on zoom in - as we should already have the markers
			if(first_time || !move_listener)	add_listeners();			
			
			
			///	if(first_time || !zoom_listener) move_listener = GEvent.addListener(map, 'moveend', redrawMap);	// Redraw on drag / pan
			//$('#debug').html('Bounds: ' + map.getBounds() +'<br><br>southwest_lat: ' + data.southwest_lat + '<br>southwest_lng: '+ data.southwest_lng + '<br>northeast_lat: ' + data.northeast_lng + '<br>northeast_lng '+ data.northeast_lng + '<br><br>Props:' + markers_count+ '<br><br>Zoom:' + map.getZoom()); // Debug baby
			$('#loading').hide();
			
		}
		
	});
	
	if( (first_time) && (markers_count==0) && ($('select[name="location"] option:selected').val()) ) move(); 
	return markers_count;
}

function addProperties(data, autozoom) {
	
	//$('#debug').text(data); // Debug baby
	
	var xml = GXml.parse(data);
	
	markers = xml.documentElement.getElementsByTagName('marker');	
	markers_count = markers.length;
	
	if(markers_count==0){
		show_message(no_props_msg);
		return;
	}
	else{
		show_message(markers_count + ' propert' + ((markers_count!=1) ? 'ies' : 'y') + ' found');
	}
	
	if(autozoom){
		// ===== Start with an empty GLatLngBounds object =====     
    	var bounds = new GLatLngBounds();
	}
	
	for (var i = 0; i < markers_count; i++) {
		
		var point = new GLatLng(parseFloat(markers[i].getAttribute('lat')),	parseFloat(markers[i].getAttribute('lng')));
		
		if(autozoom){
			// ==== Each time a point is found, extent the bounds to include it =====
        	bounds.extend(point);
		}
		
		var marker = createMarker(point, i);
		
		
		// We don't add in the replaced property as we add that in later from the global variable instead
		if(!replaced_marker || replaced_marker.property_id != markers[i].getAttribute('id')){
			map.addOverlay(marker);
		}
		else if(!replaced_marker_found && map.getBounds().containsLatLng(replaced_marker.getPoint())){	// Check whether it's in viewport
			replaced_marker_found = true;
		}
		
		// Hide markers that are in the same location as another marker
		if(markers[i].getAttribute('parent_id'))	marker.hide();
		
	}
	
	// Reset removed marker if no longer applicable
	if(replaced_marker){
		
		if (!replaced_marker_found){ // No longer in record set
		 	replaced_marker = false;
		}
		
	}
	else if(autozoom){
		
		// ===== determine the zoom level from the bounds =====
		map.setZoom(map.getBoundsZoomLevel(bounds));
		
		// ===== determine the centre from the bounds ======
		map.setCenter(bounds.getCenter());
		
		show_message(markers_count + ' propert' + ((markers_count!=1) ? 'ies' : 'y') + ' found (we\'ve zoomed the map to include all available results)');
		//alert('hold up');
	}
	
	return markers_count;

};

function getBounds(){
	alert(map.getBounds());
}

// If the map position is out of range, move it back
function checkBounds() {
	
	// Perform the check and return if OK
	if (allowedBounds.contains(map.getCenter())) {
	  return;
	}
	// It's not OK, so find the nearest allowed point and move there
	var C = map.getCenter();
	var X = C.lng();
	var Y = C.lat();
	
	var AmaxX = allowedBounds.getNorthEast().lng();
	var AmaxY = allowedBounds.getNorthEast().lat();
	var AminX = allowedBounds.getSouthWest().lng();
	var AminY = allowedBounds.getSouthWest().lat();
	
	if (X < AminX) {X = AminX;}
	if (X > AmaxX) {X = AmaxX;}
	if (Y < AminY) {Y = AminY;}
	if (Y > AmaxY) {Y = AmaxY;}
	//alert ("Restricting "+Y+" "+X);
	map.setCenter(new GLatLng(Y,X));
	
}


// Adds a property to the map inc onclick etc
function createMarker(point, marker_id) {
	//alert(markers[marker_id]);
	
	/*
	$status = array(0 => 'Under Offer',
					1 => 'Sold',
					2 => 'Available',
					3 => 'Let',
					4 => 'Withdrawn',
					5 => 'Sold STC',
					6 => 'Let STC',
					7 => 'Coming Soon',
					8 => 'Part Let'
					);
	*/
	
	///// Determine which icon we should use /////
	
	// First see if this property is sold
	var status = parseInt(markers[marker_id].getAttribute('status'));
	
	if(status != 1 && status !=3){	// Still available	
		
		// Is it a master marker representing multiple properties?
		if(!markers[marker_id].getAttribute('child_ids')){	// Solo property
			
			// Does it belong to multiple subtypes?
			var type = markers[marker_id].getAttribute('type').split(',');
			
			if(type.length == 1){	// One subtype
				var icon = customIcons[markers[marker_id].getAttribute('type')];
			}
			else{	// Multiple subtypes
				var icon = iconMultipleCat; 
			}
		
		}
		else{	// Marker represents multiple properties 
		
			var icon = iconMultiple;
			
		}
		
	}
	else{ // Sold
		
		var icon = iconSold;
	}
	
	
	var marker = new GMarker(point, icon);
	marker.property_id = markers[marker_id].getAttribute('id');
	
	// Set up the onclick 
	GEvent.addListener(marker, 'click', function(){
    	
		// Display info panel
		generate_panel(marker_id);
		
		// Show previously replaced marker..?
		if(replaced_marker) replaced_marker.show();
		
		// ..and replace this marker with active marker
		replaced_marker = marker;
		replaced_marker.hide();
		
		//alert(point);
		active_marker.setLatLng(point);
		
		if(active_marker.isHidden())	active_marker.show();
		
		//	$('img[src$=active2.png]:first').effect('pulsate', { times: 1500 });
		
	});
	
	return marker;
}


// Shows either the info panel or a choice panel as neccessary for a given marker ID
function generate_panel(marker_id){
	
	close_panel();
	
	var property = markers[marker_id];
	
	show_panel(!property.getAttribute('child_ids') ? get_info_html(marker_id) : get_choices_html(marker_id));
	
	if(property.getAttribute('child_ids')){
		$('.multi-box').hover(function() {
			$(this).addClass('pretty-hover');
		}, function() {
			$(this).removeClass('pretty-hover');
		});
	}
}

function show_panel(contents){
	//alert(contents);
	var panel = '<div id="mappr_panel">\
				   <div id="panel_bg" class="move"><\/div>\
				     <div id="content" class="move">\
					 <\/div>\
					 <a class="close" id="close_button">X<\/a>\
				  <\/div>';
	
	$('#map').append(panel);
	$('#content').html(contents);
	$('#close_button').click(close_details);
	
	
}

function close_panel(){
	$('#mappr_panel').remove();
}

function choice_made(marker_id){
	close_panel();
	show_panel(get_info_html(marker_id));
}

function show_choices(marker_id){
	close_panel();
	generate_panel(marker_id);
}

function get_choices_html(marker_id){
	
	var property = markers[marker_id];
	
	var choices_div = '<p>Please choose a property:<\/p>';
							
	$.each( (marker_id + ',' + property.getAttribute('child_ids') ).split(','), function(intIndex, child_id){
		
		var image = markers[child_id].getAttribute('image') ? 'properties/' + markers[child_id].getAttribute('image').replace('MEDIUM','THUMB') : 'awaiting_thumb.jpg';
		
		choices_div += '<div class="multi-box clearfix" onclick="choice_made(' + child_id + ')">\
							<img src="/images/' + image + '" alt="Image of property" class="choice_img" \/>\
							<p class="upper">' + markers[child_id].getAttribute('address') + '<p\/>\
							<p style="clear:both;">' + markers[child_id].getAttribute('price') + '<p\/>\
						<\/div>';
						
	});
		
	return choices_div;
	
}

// Shows info panel for a single property
function get_info_html(marker_id){
	
	var property = markers[marker_id];
	var image = property.getAttribute('image') ? 'properties/' + property.getAttribute('image') : 'awaiting_medium.jpg';
	
	var details_div = '<h3 class="column">' + property.getAttribute('address') + '<\/h3>\
					   <img src="\/images\/' + image + '" alt="Image of property" \/>\
				 	   <p class="summary-text"><strong>' + property.getAttribute('price') +'<\/strong><\/p>\
					   <p id="toggler"><a class="full-details" onclick="full_details(' + marker_id + ')">&laquo; More<\/a><\/p>';

	// Do we need to provide a "Back to choices" link?
	if(property.getAttribute('child_ids')) var m_id = marker_id;
	else if(property.getAttribute('parent_id')) var m_id = property.getAttribute('parent_id');
	if(m_id) details_div += '<a class="back-details" onclick="show_choices(' + m_id + ');">[back to choices]<\/a>';
		
	return details_div;

}

function close_details(){
	
	// Remove all the stuff to do with active property
	if(replaced_marker){
		
		replaced_marker.show();
		active_marker.hide();
		
	}
	
	// Reset these so they don't get shown following a redraw
	active_marker.property_id = -1;
	replaced_marker.property_id = -1;
	
	close_panel();

}

function zoomed(old_level, new_level){
	
	if(new_level<old_level) redrawMap();
	else{
		// We need to work out how many markers are in the viewport as we haven't reloaded the XML
		var viewport_bounds = map.getBounds();
		var mc = 0;
		for (var i = 0; i < markers_count; i++) {
			if(viewport_bounds.containsLatLng( new GLatLng(parseFloat(markers[i].getAttribute('lat')), parseFloat(markers[i].getAttribute('lng'))) )) mc++;
		}
		
		if(mc>0)	show_message(mc + ' propert' + ((mc!=1) ? 'ies' : 'y') + ' found');
		else 		show_message(no_props_msg);
	}
	//alert('new:' + new_level);
	
}

function full_details(marker_id){
	
	var property = markers[marker_id];
	quick_html = $('#content').html(); // Store the summary HTML incase we reduce the panel again
	
	$('#content').html('<img src="/images/loader.gif" alt="Content is loading" />');
	
	$.ajax({
		type: 'GET',
		url: '/mapxml/details/' + property.getAttribute('id') + '/' + marker_id,
		success: function(response){
			$('.move').animate(
				{ width: '620px' }, 
				600,
				'swing',
				function(){
					$('#content').html(response);
					$('#close_button').click(close_details);
					
				}
			);
		}
	});

}



function quick_details(marker_id){
	
	//var property = markers[marker_id];
	
	$('#content').html('<img src="/images/loader.gif" alt="Content is loading" />');
	$('.move').animate(
		{ width: '184px'}, 
		400,
		'swing',
		function(){
			//alert(quick_html);
			$('#content').html(quick_html);
			$('#close_button').click(close_details);
		}
	);
	
	  
}


function add_branches(){
	
	var branch_marker = new GMarker(new GPoint('-1.480949', '53.023417'), iconBranch);

	map.addOverlay(branch_marker);
	
}

/*function pulsate(){
	//alert($('img[src$=active2.png'));
	
	//$('img[src$=active2.png').effect("pulsate", { times: 3 }, 1000);
}*/
function move(redraw){
	
	if(redraw!=true) redraw = false;
	//alert('re: ' + redraw);
	$.ajax({
		type: 'POST',
		url: '/mapxml/location/',
		data: { location: $('select[name="location"] option:selected').val() },		
		success: function(response){
			
			var xml = GXml.parse(response);
			markers = xml.documentElement.getElementsByTagName('marker');	
			markers_count = markers.length;
			
			// ===== Start with an empty GLatLngBounds object =====     
			bounds = new GLatLngBounds();
			
			for (var i = 0; i < markers_count; i++) {
				
				var point = new GLatLng(parseFloat(markers[i].getAttribute('lat')),	parseFloat(markers[i].getAttribute('lng')));
				
				// ===== Each time a point is found, extent the bounds to include it =====
        		bounds.extend(point);
		
			}
			
			// Zoom in to only the area where properties are found, irrelevant of criteria as there is none for this function
			map.setZoom(13);
						
			// ===== determine the centre from the bounds ======
			map.panTo(bounds.getCenter());	
		
			if(redraw) redrawMap(false, bounds);
		
		}
		
	});
	
	return;
}

function remove_listeners(){
/*	GEvent.removeListener(zoom_listener);
	zoom_listener = false;*/
	GEvent.removeListener(move_listener);
	move_listener = false;
}

function add_listeners(){
//	 zoom_listener = GEvent.addListener(map, 'zoomend', zoomed);
	 move_listener = GEvent.addListener(map, 'moveend', redrawMap);	// Redraw on drag / pan
}

//var timeout;
$(document).ready( function(){

	
	// Onchange
	$('.onchange').change(redrawMap);
	
	// Keyword search stuff
	var search_timeout = false;

	$('#keyword').bind('keyup', function() {
		if(search_timeout != false) {
			clearTimeout(search_timeout);
		}
		var $this = this; // save reference to 'this' so we can use it in timeout function
		search_timeout = setTimeout(function() {
			search_timeout = false;
			str = $('#keyword').val();
			if(str.length >= 3 || str.length == 0){
				redrawMap();
			}
		}, 500);
			
	});
	
	// We need to search the UK then zoom to the results when a location changes
	$('#prop-location').change(function(){
		
		remove_listeners();
		move(true); // true denotes do a redraw too
				
	});
	
	
	mapLoad();
	
});

$(window).unload( function(){
	GUnload();				
});

