
var EXTEND_BOUNDS_BY = 0.1; // The percentage by which we expand the map bounds

var properties = []; // All properties
var visibleProperties = []; // Those that a visible in the list and on the map
var map;
var icon;
var markers = {};
var propertyDivs = []; // Reference to the divs containing the property details
var scrollingDivHeight = 0; // The height of the div we load property details into NOTE: May need to rework this if the browser window changess size
var scrollingDivContentHeight = 0; // The height of the content in the scrolling div
var averagePropertyDivHeight = 0; // A fix to a problem of calculating the height of each property detail div, we assume an average
var noOfViewablePropertyDivs = 0; // This represents the range we work on when showing and hiding property detail divs and map markers
var overMarkerImage = "";
var outMarkerImage = "";
var ready = false;

function initPropertyMap(options) {

	// The calling page will pass in an object with key-value pairs, we loop through this and create the values in a scope here
	for (var i in options) {
		this[i] = options[i];
		//alert(options[i]);
	}
	
}

$(function() {
	
	if (!noProperties) {
	
		icon = new GIcon(G_DEFAULT_ICON); icon.image = outMarkerImage; icon.iconSize = new GSize(30, 31);
	
		initScrollVars();
		
		$("#scrollingDiv").scroll(propertiesScroll);
		
		loadMap();
		
		properties = addPropertyMarkers(properties);
		
		properties = bindPropertyEvents(properties);
		
		// Trigger the scroll event to kick things off
		propertiesScroll();
		
		// Highlight the first property as if the user had hovered over it
		$(".propertyDetail:first").mouseover();
		
	}
	
});

function propertiesScroll() {
	
	currentScrollPosition = document.getElementById("scrollingDiv").scrollTop;
	startIndex = Math.round(currentScrollPosition / averagePropertyDivHeight);
	endIndex = startIndex + noOfViewablePropertyDivs;
	
	// Hide any markers that were visible
	for (var i = 0; i < visibleProperties.length; i++) {
		hideMarker(visibleProperties[i].id);
	}
	
	// We've hidden any visible markers so we clear out this array
	visibleProperties = [];

	// NOTE: Quick fix for the indexes being out
	try {			
	
		// Show and store those that we calculate are viewable
		for (var i = startIndex; i < endIndex; i++) {
			showMarker(properties[i].id);
			visibleProperties.push(properties[i]);
		}
		
	} catch (e) {
		// Do nowt
	}
	
}

function initScrollVars() {
	// Called to re-calculate any of the vars below
	scrollingDivHeight = $("#scrollingDiv").height();
	scrollingDivContentHeight = document.getElementById("scrollingDivContent").offsetHeight;
	averagePropertyDivHeight = $(".propertyDetail:first").height();
	noOfViewablePropertyDivs = Math.round(scrollingDivHeight / averagePropertyDivHeight);
}

function addPropertyMarkers(properties) {

	// Puts all properties onto the map, adds to the map bounds and attempts to extend the bounds
	
	// Add new properties to the map
	for (var i = 0; i < properties.length; i++) {
		
		var point = new GLatLng(properties[i].lat, properties[i].lng);
		var marker = createMarker(point, icon, properties.length);
		marker.getIcon().image = marker.outFilePath;
		marker.propertyID = properties[i].id;
		marker.listerURL = properties[i].listerURL;
		marker.propertyURL = properties[i].propertyURL;
		markers[marker.propertyID] = marker; // To access later
		map.addOverlay(marker);
		hideMarker(marker.propertyID); // Hide by default
		
		//alert(properties[i].url);
		
	}
	
	// Add all properties to bounds, we do this so we can calculate the extension to the bounds correctly
	// If we don't we might add a property that doesn't extend the bounds yet we STILL expand it
	
	var bounds = new GLatLngBounds();
	
	for (var i = 0; i < properties.length; i++) {
		var point = new GLatLng(properties[i].lat, properties[i].lng);
		bounds.extend(point);
	}
	
	bounds = extendBounds(bounds, EXTEND_BOUNDS_BY);
	
	map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
	
	return properties;
	
}

function bindPropertyEvents(properties) {

	// Bind the click, mouse over/out events for each property element

	// NOTE: The marker events are defined in createMarker. It would be good to have them here but it's a job for another day
	
	for (var i = 0; i < properties.length; i++) {
		
		var propertyDetail = $("#propertyDetail-" + properties[i].id);
		//propertyDetail.click(function() {propertyClick(getID(this.id))});
		propertyDetail.mouseover(function() {propertyOver(getID(this.id))});
		propertyDetail.mouseout(function() {propertyOut(getID(this.id))});
		
	}
	
	return properties;
	
}

function propertyClick(propertyID, propertyURL) {

	if (propertyURL != undefined) {
		document.location = propertyURL;
	} else {
		document.location = propertyLink + propertyID;
	}
	
}

function propertyOver(propertyID) {

	var propertyDetail = $("#propertyDetail-" + propertyID);

	// Remove all marker highlighting
	removeMarkerHighlights(markers);
	
	// Remove all property highlighting
	removePropertyHighlights();
	
	// Highlight marker
	markers[propertyID].setImage(overMarkerImage);
	
	// Move marker to front
	markers[propertyID].topMarkerZIndex();
	
	// Highlight details
	propertyDetail.addClass("highlight"); // NOTE: We may not need this
	//$(".propertyDetailHighlight", propertyDetail).show();
	
	// Show summary
	$("#propertySummary-" + propertyID).show();
	
}

function propertyOut(propertyID) {
	// Probably not needed as we leave the highlighting in place
}

function removePropertyHighlights() {
	$(".propertySummary").hide();
	$(".propertyDetailHighlight").hide();
	$(".propertyDetail").removeClass("highlight");
}

function removeMarkerHighlights(markers) {
	for (var i in markers) {
		markers[i].restoreMarkerZIndex();
		markers[i].setImage(outMarkerImage);
	}
}

function createMarker(point, icon, index) {

	var marker = new PdMarker(point, icon);
	
	// Use getIconImageFilePath if different images are needed for each marker
	marker.overFilePath = overMarkerImage;//getIconImageFilePath(index, "over");
	marker.outFilePath = outMarkerImage;//getIconImageFilePath(index, "out");
	
	GEvent.addListener(marker, "mouseover", function() {
		//alert("Property ID: " + this.propertyID);
		propertyOver(this.propertyID);
	});
	
	GEvent.addListener(marker, "mouseout", function() {
		//alert("Property ID: " + this.propertyID);
		propertyOut(this.propertyID);
	});
	
	GEvent.addListener(marker, "click", function() {
		//alert("Property ID: " + this.propertyID);
		propertyClick(this.propertyID, this.propertyURL);
	});
	
	return marker;

}

function extendBounds(bounds, percentage) {

	// Extend the bounds by the given percentage

	if (percentage != 0) {
		
		sw = bounds.getSouthWest(); // Returns the point at the south-west corner of the rectangle
		ne = bounds.getNorthEast(); // Returns the point at the north-east corner of the rectangle
		
		latDiff = ne.lat() - sw.lat();
		lngDiff = ne.lng() - sw.lng();
		
		extraSW = new GLatLng(sw.lat() - (latDiff * percentage), sw.lng() - (lngDiff * percentage));
		extraNE = new GLatLng(ne.lat() + (latDiff * percentage), ne.lng() + (lngDiff * percentage));
		
		bounds.extend(extraSW);
		bounds.extend(extraNE);
		
	}
	
	return bounds;
	
}

function hideMarker(id) {
	//alert("Hiding property: " + id);
	markers[id].display(false);
}

function showMarker(id) {
	markers[id].display(true);
}

function loadMap() {
	
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		map.setCenter(new GLatLng(53.9487, -3.5156), 5); // Just to start with, we'll re-centre later if needed
	} else {
		alert("Google Maps doesn't seem to work in this browser");
	}
	
}

function getID(idString) {
	// Returns the number portion from a string in the form of "something-101"
	return idString.split("-")[1];
}