var map = null;
var mgr = null;
var gIcons = [];
var gMarkers = [];	// marker groups
var gCurFrame = 0, gTimeline = {}, gLocations = {};	// timeline variables

function createCustomMap ()
{
	// ====== Create the Euclidean Projection for the flat map ======
	// == Constructor ==
	function EuclideanProjection(a)
	{
		this.pixelsPerLonDegree=[];
		this.pixelsPerLonRadian=[];
		this.pixelOrigo=[];
		this.tileBounds=[];
		var b=256;
		var c=1;
		for(var d=0;d<a;d++)
		{
			var e=b/2;
			this.pixelsPerLonDegree.push(b/360);
			this.pixelsPerLonRadian.push(b/(2*Math.PI));
			this.pixelOrigo.push(new GPoint(e,e));
			this.tileBounds.push(c);
			b*=2;
			c*=2
		}
	}

	// == Attach it to the GProjection() class ==
	EuclideanProjection.prototype=new GProjection();

	// == A method for converting latitudes and longitudes to pixel coordinates ==
	EuclideanProjection.prototype.fromLatLngToPixel=function(a,b)
	{
		var c=Math.round(this.pixelOrigo[b].x+a.lng()*this.pixelsPerLonDegree[b]);
		var d=Math.round(this.pixelOrigo[b].y+(-2*a.lat())*this.pixelsPerLonDegree[b]);
		return new GPoint(c,d)
	};

	// == a method for converting pixel coordinates to latitudes and longitudes ==
	EuclideanProjection.prototype.fromPixelToLatLng=function(a,b,c)
	{
		var d=(a.x-this.pixelOrigo[b].x)/this.pixelsPerLonDegree[b];
		var e=-0.5*(a.y-this.pixelOrigo[b].y)/this.pixelsPerLonDegree[b];
		return new GLatLng(e,d,c)
	};

	// == a method that checks if the y value is in range, and wraps the x value ==
	EuclideanProjection.prototype.tileCheckRange=function(a,b,c)
	{
		var d=this.tileBounds[b];
		if (a.y<0||a.y>=d) {
		  return false;
		}
		if(a.x<0||a.x>=d){
		  a.x=a.x%d;
		  if(a.x<0){
			a.x+=d;
		  }
		}
		return true
	}

	// == a method that returns the width of the tilespace ==
	EuclideanProjection.prototype.getWrapWidth=function(zoom)
	{
		return this.tileBounds[zoom]*256;
	}

	setupIconImages();

	var copyright = new GCopyright(
		1, new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180) ),
		0, "(c) Tower of the Hand");

	var copyrights = new GCopyrightCollection("Map");
	copyrights.addCopyright(copyright);

	map = new GMap2(document.getElementById("map"));

	var labelTiles = [new GTileLayer(copyrights,0,4), new GTileLayer(copyrights,2,4)];
	labelTiles[0].getTileUrl = getBaseTileUrl;
	labelTiles[1].getTileUrl = getLabelTileUrl;

	var labelMap = new GMapType(
		labelTiles,
		new EuclideanProjection(18),
		"Labels",{errorMessage:"Error loading labels map."});

	map.addMapType(labelMap);

	var baseTiles = [new GTileLayer(copyrights,0,4)];
	baseTiles[0].getTileUrl = getBaseTileUrl;
	var baseMap = new GMapType(
		baseTiles,
		new EuclideanProjection(18),
		"Map Only",{errorMessage:"Error loading base map."});

	map.addMapType(baseMap);

	map.removeMapType(G_HYBRID_MAP);
	map.removeMapType(G_SATELLITE_MAP);
	map.removeMapType(G_NORMAL_MAP);

	centerMap();

	map.addControl(new GLargeMapControl());
	//map.addControl(new GMenuMapTypeControl(false, false));

	var omap=new GOverviewMapControl(new GSize(175,115));
	map.addControl(omap);
	omap.hide(true);

	map.enableContinuousZoom();
	map.enableScrollWheelZoom();
}

function centerMap ()
{
	var cDefault = new Array(2);
	cDefault[1] = new GLatLng(-36.5,-73.5);

	var zDefault = 3;

	// skip the first character, we are not interested in the "?"
	var query = location.search.substring(1);

	// split by & to give a list of "argname=value" pairs
	var pairs = query.split("&");

	var lat, lng, zoom;

	for (var i=0; i<pairs.length; i++)
	{
		// use = to separate argname from value
		var pos = pairs[i].indexOf("=");
		var argname = pairs[i].substring(0,pos).toLowerCase();
		var value = pairs[i].substring(pos+1).toLowerCase();

		switch (argname)
		{
			case "lat":
				lat = parseFloat(value);
				break;
			case "lng":
				lng = parseFloat(value);
				break;
			case "zoom":
				zoom = parseInt(value);
				break;
		}
	}

	var pCenter;
	if (lat && lng)
		pCenter = new GLatLng(lat,lng);
	else
		pCenter = cDefault[mapId];

	var iZoom;
	if (zoom)
		iZoom = zoom;
	else
		iZoom = zDefault;

	map.setCenter(pCenter, iZoom);
}

function setupIconImages ()
{
	var baseIcon = new GIcon();
	baseIcon.iconSize = new GSize(32,32);
	baseIcon.shadowSize = new GSize(56,32);
	baseIcon.iconAnchor = new GPoint(12,32);
	baseIcon.infoWindowAnchor = new GPoint(16,0);

	var halfIcon = new GIcon();
	halfIcon.iconSize = new GSize(16,16);
	halfIcon.iconAnchor = new GPoint(8,16);
	halfIcon.infoWindowAnchor = new GPoint(12,4);
	halfIcon.transparent = "http://mts.towerofthehand.com/markers/circlesmallt.png";
	halfIcon.imageMap = [10,2,11,3,12,4,13,5,13,6,13,7,13,8,13,9,13,10,12,11,11,12,10,13,5,13,3,12,3,11,2,10,2,9,2,8,2,7,2,6,2,5,3,4,3,3,5,2];

	gIcons["whiteflag"] = new GIcon(
		baseIcon, "http://mts.towerofthehand.com/markers/whiteflag.png",
		null, "http://mts.towerofthehand.com/markers/whiteflags.png");

	gIcons["smallcircle"] = new GIcon(
		halfIcon, "http://mts.towerofthehand.com/markers/circlesmall.png",
		null, null);
}

function createMarker (point, name, html, icon)
{
	var marker = new GMarker(point, {title:name, icon:gIcons[icon]});
	GEvent.addListener(marker, "click",
		function()
		{
			marker.openInfoWindowHtml( '<div class="infowindow">' + html + '<\/div>' );
		}
	);
	return marker;
}

function createShield (point, name, html, capital)
{
	var shieldIcon = new GIcon();
	shieldIcon.iconSize = new GSize(48,48);
	shieldIcon.shadowSize = new GSize(72,48);
	shieldIcon.iconAnchor = new GPoint(24,48);
	shieldIcon.infoWindowAnchor = new GPoint(24,0);
	shieldIcon.transparent = "http://mts.towerofthehand.com/markers/shields/shieldt.png";
	shieldIcon.imageMap = [29,0,31,1,33,2,35,3,37,4,39,5,42,6,44,7,45,8,46,9,46,10,47,11,47,12,47,13,47,14,47,15,47,16,47,17,47,18,47,19,47,20,47,21,47,22,47,23,46,24,46,25,46,26,45,27,45,28,44,29,44,30,44,31,43,32,43,33,42,34,41,35,41,36,40,37,39,38,39,39,38,40,37,41,36,42,35,43,34,44,33,45,32,46,31,47,16,47,15,46,14,45,13,44,12,43,11,42,10,41,9,40,9,39,8,38,7,37,7,36,6,35,5,34,5,33,4,32,4,31,3,30,3,29,2,28,2,27,2,26,1,25,1,24,1,23,0,22,0,21,0,20,0,19,0,18,0,17,0,16,0,15,0,14,0,13,0,12,0,11,1,10,2,9,2,8,4,7,6,6,8,5,10,4,12,3,14,2,16,1,19,0];
	shieldIcon.shadow = "http://mts.towerofthehand.com/markers/shields/shields.png"
	shieldIcon.image = "http://mts.towerofthehand.com/markers/shields/"+capital.toLowerCase().replace(/[^a-z]/g, "")+".png"

	var marker = new GMarker(point, {title:name, icon:shieldIcon});
	GEvent.addListener(marker, "click",
		function()
		{
			marker.openInfoWindowHtml( '<div class="infowindow">' + html + '<\/div>' );
		}
	);
	return marker;
}

function createLabel (point, name, type, clock)
{
	var width, height, icon;
	if (type == "capital")
	{
		width = 108;
		height = 24;
		icon = 48;
		type = "city_in";
	}
	else if (type == "city_in")
	{
		width = 108;
		height = 24;
		icon = 32;
	}
	else
	{
		width = 90;
		height = 20;
		icon = 16;
	}

	var offsetX = 0, offsetY = 0;
	switch (clock)
	{
		case 2:
		case 3:
		case 4:
			offsetX = icon/2;
			break;
		case 5:
		case 6:
		case 7:
			offsetX = width/-2;
			offsetY = height-2;
			break;
		case 8:
		case 9:
		case 10:
			offsetX = -width-8;
			break;
		case 11:
		case 12:
		case 1:
			offsetX = width/-2;
			offsetY = icon*-1+1;
			break;
		default:
			offsetX = 0;
			offsetY = 0;
	}

	var tdClass;
	switch (clock)
	{
		case 2:
		case 3:
		case 4:
		case 7:
		case 11:
			tdClass = "left";
			break;
		case 1:
		case 5:
		case 8:
		case 9:
		case 10:
			tdClass = "right";
			break;
		default:
			tdClass = "center";
	}
	switch (clock)
	{
		case 2:
		case 5:
		case 6:
		case 7:
		case 10:
			tdClass = tdClass + " top";
			break;
		case 4:
		case 8:
		case 11:
		case 12:
		case 1:
			tdClass = tdClass + " bottom";
			break;
		default:
			tdClass = tdClass + " middle";
	}

	var html = '<table class="label_table"><tr><td class="' + tdClass + '">' + name + '<\/td><\/tr><\/table>';
	var label = new ELabel (point, html, type + " onterrain", new GSize(parseInt(offsetX), parseInt(offsetY)));
	return label;
}

function createTimeMarker (point, location, icon)
{
	var marker = new GMarker(point, {title:location, icon:gIcons[icon]});
	GEvent.addListener(marker, "click",
		function()
		{
			var chapterId = gCurFrame;

			// Determine place in gTimeline
			//  If unset, use first reference to location
			var chapterData = gLocations[location][chapterId.toString()];
			if (chapterData == undefined)
			{
				chapterId = 1024;
				for (var chapter in gLocations[location])
				{
					if (parseInt(chapter) < chapterId)
						chapterId = parseInt(chapter);
				}
			}

			gCurFrame = chapterId;
			chapterId = chapterId.toString();

			var chapter = gLocations[location][chapterId].chapter;
			var info = gLocations[location][chapterId].info;

			var html = '<p class="subject">' + chapter + '<\/p>' +
				'<p class="teaser">' + location.toUpperCase() + ' - ' + info + '<\/p>' +
				'<p class="link"><a href="javascript:timelinePrevious()">Previous<\/a> - <a href="javascript:timelineNext()">Next<\/a><\/p>';

			marker.openInfoWindowHtml( '<div class="infowindow">' + html + '<\/div>' );
		}
	);
	return marker;
}

function toggleMarkers ()
{
	map.getInfoWindow().hide();
	mgr.toggle();
}

function locateMarker (title, group, zoom)
{
	var markers = null;
	for (var i = 0; i < gMarkers.length; i++)
	{
		if (gMarkers[i].group == group)
		{
			markers = gMarkers[i].markers;
			break;
		}
	}

	if (!markers) return;

	if (map.getZoom() > zoom) zoom = map.getZoom();

	var marker = null;
	for (var j = 0; j < markers[zoom].length; j++)
	{
		if (markers[zoom][j].getTitle() == title)
		{
			marker = markers[zoom][j];
			break;
		}
	}

	if (!marker) return;

	map.getInfoWindow().hide();
	map.setZoom(zoom);
	center = marker.getPoint();
	map.panTo(center);
	GEvent.trigger(marker, "click");
}

function locatePoint (lat, lng, zoom)
{
	map.getInfoWindow().hide();
	if (zoom) map.setZoom(zoom);

	var center = new GLatLng(lat,lng)
	map.panTo(center);
}

function timelinePrevious ()
{
	var previous = 0;
	for (var chapter in gTimeline)
	{
		var iChapter = parseInt(chapter);
		if (iChapter < gCurFrame && iChapter > previous)
			previous = iChapter;
	}

	if (previous == 0) return;

	gCurFrame = previous;

	var marker = gTimeline[gCurFrame.toString()];
	if (marker.isHidden())
	{
		map.getInfoWindow().hide();
		map.panTo(marker.getPoint());
	}

	GEvent.trigger(marker, "click");
}

function timelineNext ()
{
	var next = 1024;
	for (var chapter in gTimeline)
	{
		var iChapter = parseInt(chapter);
		if (iChapter > gCurFrame && iChapter < next)
			next = iChapter;
	}

	if (next == 1024) return;

	gCurFrame = next;

	var marker = gTimeline[gCurFrame.toString()];
	if (marker.isHidden())
	{
		map.getInfoWindow().hide();
		map.panTo(marker.getPoint());
	}

	GEvent.trigger(marker, "click");
}
