//coords:
//data_8_4 - name
//data_9_4 - coords
//data_10_4 - userid
//id - object id

function Maps(containerName, options)
{

//Конфигурационные поля
	this.buildingIconURL = "http://alexxei.com/maps/css/images/building.png";

	this.manIconURL = "http://alexxei.com/maps/css/images/man.png";

//Методы
	this.CreateGMaps = function(containerName)
	{
		this.container = document.getElementById(containerName);
		var map = new GMap2(this.container);
		map.setCenter(new GLatLng(23, 0), 5, G_HYBRID_MAP);
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		return map;
	}
	
	this.SetStaticObjectCoordinates = function(staticObjectCoordinates)
	{
		if ((staticObjectCoordinates != undefined) && (staticObjectCoordinates != null))
			for (var i = 0; i < staticObjectCoordinates.length; i++)
				this.staticObjectCoordinates[staticObjectCoordinates[i].id] = {
						name: staticObjectCoordinates[i].name,
						coordinates: staticObjectCoordinates[i].coords
					}
	}

	this.SetUsers = function(users)
	{
		if ((users != undefined) && (users != null))
			for (var i = 0; i < users.length; i++)
				this.users[users[i].id] = {
						login: users[i].name,
						time: users[i].time * 1000,
						coordinates: 
							{
								x: users[i].x,
								y: users[i].y
							}
					}
	}

	this.SetTrackingType = function(trackingType)
	{
		if ((trackingType != undefined) && (trackingType != null) && (trackingType != this.trackingType))
		{
			switch (trackingType)
			{
			case "none":
				this.trackingType = "none";
				this.RemoveDynamicObjects();
				break;
			case "realtime":
				this.trackingType = "realtime";
				this.UpdateRealtimeDynamicObjects();
				break;
			case "period":
				this.trackingType = "period";
				this.RemoveDynamicObjects();
				break;
			default:
				;
			}
		}
	}

	this.SetTime = function(startTime, endTime)
	{
		if (this.trackingType == "period")
			this.RemoveDynamicObjects();
		if ((startTime != undefined) && (endTime != undefined) && (startTime instanceof Date) && (endTime instanceof Date))
		{
			this.startTime = startTime.getTime() / 1000;
			this.endTime = endTime.getTime() / 1000;
		}
		else
		{
			this.startTime = undefined;
			this.endTime = undefined;
		}
	}
	
	this.ZoomToStaticObject = function(object)
	{
		var bestZoom = this.map.getBoundsZoomLevel(object.getBounds());
		if (bestZoom >= 19)
			bestZoom = 18;
		this.map.setCenter(object.getBounds().getCenter(), bestZoom);
	}

	this.ZoomToLocation = function(dir)
	{
		this.map.setCenter(dir.getPolyline().getVertex(0), 12);
	}

	this.RemoveLayers = function(layers)
	{
		for (var i in layers)
			if (typeof layers[i] != "function")
				this.map.removeOverlay(layers[i]);
	}

	this.ShowStaticObjectAtCenter = function(id)
	{
		if (this.staticObjectLayers[id] != undefined)
			this.ZoomToStaticObject(this.staticObjectLayers[id]);
		else
			this.LoadStaticObjectLayer(id, true);
	}

	this.ShowAllStaticObjects = function()
	{
		this.staticObjectIcon = this.CreateIcon(this.buildingIconURL);
		for (var i = 0; i < this.staticObjectCoordinates.length; i++)
			if (this.staticObjectLayers[i] == undefined)
				this.LoadStaticObjectLayer(i, false);
	}

	this.RegionToObject = function(id)
	{
		this.RemoveStaticObject(id);
		if (this.editRegion.layers[2] != undefined)
		{
			this.staticObjectLayers[id] = this.editRegion.layers[2];
			delete this.editRegion.layers[2];
		}
		this.ZeroEditRegion();
		this.ShowStaticObjectAtCenter(id);
	}

	this.RemoveStaticObject = function(id)
	{
		if (this.staticObjectLayers[id] != undefined)
		{
			this.map.removeOverlay(this.staticObjectLayers[id]);
			delete this.staticObjectLayers[id];
		}
	}

	this.NavigateToLocation = function(name)
	{
		var dir = new GDirections();
		dir.loadFromWaypoints([name, name], {getPolyline: true, getSteps: true});
		GEvent.bind(dir, "load", this, this.ZoomToLocation);
		GEvent.addListener(dir, "error", function()
			{
				//alert("Location not recognised. Code: " + dirn.getStatus().code);
				alert("Location not recognised. Please specify in another way.");
			});
	}
	
	this.CreateIcon = function(url)
	{
		var icon = new GIcon();
		icon.image = url;
		icon.iconSize = new GSize(32, 32);
		icon.iconAnchor = new GPoint(10, 20); 
		icon.infoWindowAnchor = new GPoint(10, 0);
		return icon;
	}
	
	this.CreateStaticMarker = function(point, icon, name)
	{
		var marker = new GMarker(point, {icon: icon, title: ""}); 
		marker.name = "<h3>" + name + "</h3>";
		marker.map = this.map;
		GEvent.addListener(marker, "mouseover", function()
			{
				this.openInfoWindowHtml(this.name);
			});
		GEvent.addListener(marker, "click", function()
			{
				this.map.setCenter(this.getLatLng(), 12);
			});
		return marker;
	}
	
	this.CreateDynamicMarker = function(id, icon)
	{
		var marker = new GMarker(new GLatLng(this.users[id].coordinates.x, this.users[id].coordinates.y), {icon: icon, title: ""});
		var date = new Date(this.users[id].time);
		marker.name = "<h3 class='google_baloon'><div>" + this.users[id].login + " last seen:</div><div>" + date.toDateString() + " " + date.toTimeString() + "</div></h3>"
		marker.map = this.map;
		GEvent.addListener(marker, "mouseover", function()
			{
				this.openInfoWindowHtml(this.name);
			});
		GEvent.addListener(marker, "click", function()
			{
				this.map.setCenter(this.getLatLng(), 12);
			});
		return marker;
	}
	
	this.LoadStaticObjectLayer = function(id, showAll)
	{
		if (this.staticObjectCoordinates[id] != undefined)
		{
			var polylines = Array();
			for (var i = 0; i < this.staticObjectCoordinates[id].coordinates.length; i++)
			{
				var coordinate = this.staticObjectCoordinates[id].coordinates[i];
				polylines.push(new GLatLng(coordinate.x, coordinate.y));
			}
			this.staticObjectLayers[id] = new GPolyline(polylines, "#0000FF", 2, 1);
			this.map.addOverlay(this.staticObjectLayers[id]);
			if (showAll)
				this.ShowStaticObjectAtCenter(id);
			else
			{
				this.map.addOverlay(this.CreateStaticMarker(this.staticObjectLayers[id].getBounds().getCenter(), this.staticObjectIcon, this.staticObjectCoordinates[id].name));
			}
		}
	}
	
	this.GetEditRegion = function()
	{
		if (this.editRegion.completed)
			return this.editRegion.polyline;
		else
			return null;
	}

	this.ZeroEditRegion = function()
	{
		if (this.editRegion != null)
			this.RemoveLayers(this.editRegion.layers);
		this.editRegion = {
				completed: false,
				polyline: Array(),
				layers: Array()
			};
	}

	this.UpdateRegion = function()
	{
		this.RemoveLayers(this.editRegion.layers);
		this.editRegion.layers = Array();
		if (this.editRegion.polyline.length > 0)
		{
			if (!this.editRegion.completed)
			{
				this.editRegion.layers[0] = new GMarker(this.editRegion.polyline[0]);
				this.editRegion.layers[0].type = "start";
				this.editRegion.layers[1] = new GMarker(this.editRegion.polyline[this.editRegion.polyline.length - 1]);
				this.editRegion.layers[1].type = "end";
			}
			this.editRegion.layers[2] = new GPolyline(this.editRegion.polyline, "#0000FF", 2, 1);
			if (!this.editRegion.completed)
				for (var i = 0; i < this.editRegion.layers.length; i++)
					this.map.addOverlay(this.editRegion.layers[i]);
			else
				this.map.addOverlay(this.editRegion.layers[2]);
			this.ZoomToStaticObject(this.editRegion.layers[2]);
		}
	}

	this.OnMapClick = function(overlay, point)
	{
		if (point) //background clicked
		{ 	
			if (this.editRegion.completed)
				this.ZeroEditRegion();
			this.editRegion.polyline.push(point); 
		}
		else if (overlay) //marker clicked
		{
			if (overlay.type == "start")
			{
				this.editRegion.polyline.push(overlay.getPoint());
				this.editRegion.completed = true;
			}
			else if (overlay.type == "end")
				this.editRegion.polyline.pop();
		}
		this.UpdateRegion();
	}

	this.ShowDynamicObjectAtCenter = function(id, callback)
	{
		switch (this.trackingType)
		{
		case "realtime":
			if (this.dynamicObjectLayers[id] != undefined)
				this.map.setCenter(this.dynamicObjectLayers[id].getLatLng(), 12);
			break;
		case "period":
			if (this.dynamicObjectLayers[id] != undefined)
				if (this.dynamicObjectLayers[id].loadedCorrectly())
					this.dynamicObjectLayers[id].gotoDefaultViewport(this.map);
				else
				{
					if (callback)
						alert(this.users[id].login + " - problem with load");
					else
						alert(this.users[id].login + " - wait untill it loads");
				}
			else
				this.LoadDynamicObjectLayer(id);
		}
	}

	this.ShowRealtimeDynamicObjects = function()
	{
		if (this.dynamicObjectIcon == undefined)
			this.dynamicObjectIcon = this.CreateIcon(this.manIconURL);
		for (var key in this.users)
			if (typeof this.users[key] != "function")
			{
				this.dynamicObjectLayers[key] = this.CreateDynamicMarker(key, this.dynamicObjectIcon);
				this.map.addOverlay(this.dynamicObjectLayers[key]);
			}
	}

	this.UpdateRealtimeDynamicObjects = function()
	{
		this.RemoveDynamicObjects();
		this.ShowRealtimeDynamicObjects();
	}

	this.LoadDynamicObjectLayer = function(id)
	{
		if ((this.startTime != undefined) && (this.endTime != undefined))
		{
			this.AddLoad();
			this.dynamicObjectLayers[id] = new GGeoXml("http://alexxei.com/index.php?AJAX=1&do=map&type=kml&id=" + id + "&starttime=" + this.startTime + "&endtime=" + this.endTime + "&timezone=" + (new Date()).getTimezoneOffset() * 60);
			//this.dynamicObjectLayers[id] = new GGeoXml("http://track.clabs.eu/kml/?starttime=1214895120&endtime=1214985120&timezone=-10800&type=getall&statObjId=&userid=&pin=2458b3a3");
			//jQuery("#trackingType").text("http://alexxei.com/index.php?AJAX=1&do=map&type=kml&id=" + id + "&starttime=" + this.startTime + "&endtime=" + this.endTime + "&timezone=" + (new Date()).getTimezoneOffset() * 60);
			this.dynamicObjectLayers[id].id = id;
			this.dynamicObjectLayers[id].map = this;
			GEvent.addListener(this.dynamicObjectLayers[id], "load", function()
			{
				this.map.RemoveLoad();
				this.map.ShowDynamicObjectAtCenter(this.id, true);
			});
			this.map.addOverlay(this.dynamicObjectLayers[id]);
		}
	}

	this.RemoveDynamicObjects = function()
	{
		this.RemoveLayers(this.dynamicObjectLayers);
		this.dynamicObjectLayers = Array();
	}

	this.AddLoad = function()
	{
		var loadDiv = document.createElement("DIV");
		loadDiv.className = "loading";
		loadDiv.style.position = "absolute";
		loadDiv.appendChild(document.createElement("DIV"));
		this.container.appendChild(loadDiv);
	}
	
	this.RemoveLoad = function()
	{
		for (var i = 0; i < this.container.childNodes.length; i++)
			if (this.container.childNodes[i].className == "loading")
			{
				this.container.removeChild(this.container.childNodes[i]);
				break;
			}
	}
	
	this.ShowInfo = function(id)
	{
		if (this.dynamicObjectLayers[id] != undefined)
			this.dynamicObjectLayers[id].openInfoWindowHtml(this.dynamicObjectLayers[id].name);
	}

//Инициализация

	//Карта (google map)
	this.map = this.CreateGMaps(containerName);

	//Статические объекты
	this.staticObjectCoordinates = Array();

	//Пользователи (динамические объекты)
	this.users = Array();

	//Вид трекинга
	this.trackingType = "none";

	//Слои с статическими объектами на карте
	this.staticObjectLayers = Array();
	
	//Слои с динамическими объектами на карте
	this.dynamicObjectLayers = Array();

	//Начальное время для треков
	this.startTime = undefined;

	//Конечное время для треков
	this.endTime = undefined;

	//Описание области, редактируемой при клике на карту
	this.editRegion = null;
	this.ZeroEditRegion();
	
	if (options != undefined)
	{
		this.SetStaticObjectCoordinates(options.staticObjectCoordinates);

		this.SetUsers(options.users);

		this.SetTrackingType(options.trackingType);

		if ((options.editable != undefined) && (options.editable != null) && (options.editable == true))
			GEvent.bind(this.map, "click", this, this.OnMapClick);
	}
}