window.GoogleMapChooserMap = null;
window.GoogleMapChooserMarkers = [];

/**
 * Initialize the Google map.
 *
 * @param {jQuery} input The input that represents the gps location(s).
 * @param {function} onReadyCallback The callback to call when map is ready.
 */
function GoogleMapChooser(input, onReadyCallback) {
	this._this = this;

	/** @var {string} The id of the DOM element which shows the map itself. */
	this.id = 'GoogleMapLocationPicker';

	/** @var {jQuery} The target form text input which will receive the selection. */
	this.input = input;

	/** @var @param {function} The callback to call when map is ready. */
	this.onReadyCallback = onReadyCallback;

	/** @var {bool} Shows weather this map is used to select multiple points, or a single one. */
	this.multiple = this.input.data('multiple');

	/** @var {jQuery} The text input element which shows the current selection. */
	this.selected = $('#GoogleMapSelection');

	/** @var {jQuery} The button which acts as a submit button. */
	this.submit = $('#GoogleMapSubmit');

	// Initialize
	this.initialize();
}

/**
 * Shows the map and allows the user to pick a location(s).
 */
GoogleMapChooser.prototype.initialize = function () {
	var _this = this;

	// Build map only once
	if (window.GoogleMapChooserMap === null) {

		// Get the map options
		var mapOptions = {

			// Controls
			disableDefaultUI: true,
			zoomControl: true,
			mapTypeControl: true,

			// Default position and settings
			zoom: 1 * window.Configuration.Backend.map_zoom,
			center: new google.maps.LatLng(1.0 * window.Configuration.Backend.map_latitude, 1.0 * window.Configuration.Backend.map_longitude),
			mapTypeId: google.maps.MapTypeId[window.Configuration.Backend.map_type]
		};

		// Create google map object in dialog
		window.GoogleMapChooserMap = new google.maps.Map(document.getElementById("GoogleMapLocationPicker"), mapOptions);
	}

	// Load markers from the input
	this.loadMarkersFromString(this.input.val());

	// Place a marker on left click
	google.maps.event.clearListeners(window.GoogleMapChooserMap, 'click');
	google.maps.event.addListener(window.GoogleMapChooserMap, 'click', function (event) {
		_this.placeMarker(event.latLng);
	});

	// Show only when ready
	google.maps.event.addListenerOnce(window.GoogleMapChooserMap, 'idle', function () {
		if (typeof _this.onReadyCallback === 'function') {
			_this.onReadyCallback(_this);
		}
	});

	// Submit
	this.submit.unbind('click');
	this.submit.click(function () {
		_this.input.val(_this.selected.val());
		ShowUp.goHide();
	});

};

/**
 * Loads the markers from the supplied string.
 *
 * @param {string} value The value from which to load the markers.
 *
 * @return {marker[]} The list of parsed markers
 */
GoogleMapChooser.prototype.loadMarkersFromString = function (value) {

	// Remove all markers
	this.clear();

	// Get all coordinates
	try {
		var split = value.trim().split(';');
		for (var i in split) {
			try {
				var coordinates = split[i].trim().split(',');
				this.placeMarker(new google.maps.LatLng(1.0 * coordinates[0].trim(), 1.0 * coordinates[1].trim()));
			} catch (e) {
			}
		}
	} catch (e) {
	}

	// Change zoom so that the map is forced to be redrawn
	window.GoogleMapChooserMap.setZoom(1);

	// Show the proper location and zoom, based on the markers
	var len = window.GoogleMapChooserMarkers.length;
	switch (len) {

		// No markers, show the default position
		case 0:
			window.GoogleMapChooserMap.setZoom(1 * window.Configuration.Backend.map_zoom);
			window.GoogleMapChooserMap.setCenter(new google.maps.LatLng(1.0 * window.Configuration.Backend.map_latitude, 1.0 * window.Configuration.Backend.map_longitude));
			break;

		// One marker, center on it with default zoom
		case 1:
			window.GoogleMapChooserMap.setZoom(1 * window.Configuration.Backend.map_zoom);
			window.GoogleMapChooserMap.setCenter(window.GoogleMapChooserMarkers[0].getPosition());
			break;

		// Multiple markers, make sure all are visible
		default:
			var bounds = new google.maps.LatLngBounds();
			for (var m = 0; m < len; m++) {
				bounds.extend(window.GoogleMapChooserMarkers[m].getPosition());
			}
			window.GoogleMapChooserMap.fitBounds(bounds);
	}
};

/**
 * Clear all markers from the map.
 */
GoogleMapChooser.prototype.clear = function () {
	for (var i = 0; i < window.GoogleMapChooserMarkers.length; i++) {
		window.GoogleMapChooserMarkers[i].setMap(null);
	}

	window.GoogleMapChooserMarkers = [];
	this.refreshSelection();
};

/**
 * Repopulate the input with the selected markers
 */
GoogleMapChooser.prototype.refreshSelection = function () {
	var markers = [];
	for (var i in window.GoogleMapChooserMarkers) {
		markers.push(window.GoogleMapChooserMarkers[i].position.lat().toFixed(6) + "," + window.GoogleMapChooserMarkers[i].position.lng().toFixed(6));
	}

	this.selected.val(markers.join(';'));
};

/**
 * Place a marker on map.
 *
 * @param {google.maps.LatLng} position The position to place the marker
 */
GoogleMapChooser.prototype.placeMarker = function (position) {
	var _this = this;

	// Create new marker.
	var marker = new google.maps.Marker({
		position: position,
		map: window.GoogleMapChooserMap
	});

	// Add remove listener
	google.maps.event.addListener(marker, 'click', function () {
		marker.setMap(null);
		window.GoogleMapChooserMarkers.splice(window.GoogleMapChooserMarkers.indexOf(marker), 1);
		_this.refreshSelection();
	});

	// Add to the map, but take care if multiple is allowed or not
	if (!this.multiple) {
		this.clear();
	}
	window.GoogleMapChooserMarkers.push(marker);

	this.refreshSelection();
};


// Load the google maps, if there are at least one GPS location input
$(document).ready(function () {
	if ($('a.showup.gmap').length > 0) {
		var script = document.createElement("script");
		script.id = "gmapsScript";
		script.type = "text/javascript";
		script.src = "//maps.googleapis.com/maps/api/js?key=" + window.Configuration.Backend.map_key;
		document.body.appendChild(script);
	}
});