var points=[];
var marker=[];
var poly=[];
var line=[];
var myline;
var map;
var blogs = [];

var newmarker; // marker for adding single new location

var blogicon;
var diveicon;
var blueicon;
var greenicon;
var redicon;
var pulseicon;
var yellowicon;
var changed;



var last_point; // = new GLatLng(0,0);

function get_blog(id,infoWin) {
if (!id) return 'No Id';
ajax_get_file('/ajax/blogs.php?blog_id='+id,display_in_window(infoWin))
}

function toggle_show_points() {
if (show_points) {
	show_points = false;
} else {
	show_points = true;
}
if (editable) {
	new_draw_edit_points(points);
} else {
	new_draw_points(points);
}
}


function toggle_show_line() {
                if (show_line) {
                        show_line = false;
                } else {
                        show_line = true;
                }
	draw(); // When lines are editable - need two options
}


function get_total_distance(points) {
	var count = points.length;
	var total_distance=0;

	for (var i=1;i<count;i++) {
		total_distance += points[i].distanceFrom(points[i-1]);
        }

	return total_distance;
}

function show_line_info(points) {
	var total_distance = get_total_distance(points);

	var a = normalise_units(total_distance);
	document.getElementById('total_dist_miles').innerHTML = a['miles'];
	document.getElementById('total_dist_km').innerHTML = a['kilometers'];


}

function new_add_blog(x,y,blog_id) {
	blogs.push(blog_id);
        points.push(new GLatLng(y,x));
        last_point = new GLatLng(y,x);
}



function new_add_leg(x,y) {
        points.push(new GLatLng(y,x));
        last_point = new GLatLng(y,x);
}

function update_points() {
        // ok - go through each of the markers and points if they differ
for(var n=0;n<points.length;n++) {
if (marker[n]) {
var np = marker[n].getPoint();
        if (np.x !== points[n].x || np.y !== points[n].y) {
                points[n] = new GLatLng(np.y,np.x)
        }
};
}
}

function new_draw_edit_points(points) {// Create map version
//alert('show_points: ' +show_points);
for(var n=0;n<points.length;n++) {
	if (marker[n]) map.removeOverlay(marker[n]); // clear the old marker...
	if (show_points == true) {
		if (n==0) ticon = greenicon
		else if (n==points.length-1) ticon=redicon
		else ticon=yellowicon
		marker[n] = new GMarker(points[n], {icon:ticon, draggable: true, title:'point ' +n});
		marker[n].enableDragging();
		GEvent.addListener(marker[n],'drag',function() {if (points.length < 20) {update_points(); draw()}}); // performance!
		GEvent.addListener(marker[n],'dragend',function() {update_points(); draw()});
		map.addOverlay(marker[n]);
	} else {
		marker[n] = new GMarker(points[n], {title:'point ' +n});
	}
}
//alert('Marker: '+marker.length);
}

function renderLocationWindow(id) {
		return function(text) {document.getElementById('_location_' +id).innerHTML = text;}
		// apparently this is a curried function?... I like curry.
}

function renderInfoWindow(id) {
		return function(text) {document.getElementById('_blog_' +id).innerHTML = text;}
		// apparently this is a curried function?... I like curry.
}

function newBlogMarker(point,ix) {
        var marker = new GMarker(point, {icon:blogicon, draggable: false, title:'Blog Entry ' + blogs[ix]});
        GEvent.addListener(marker,'click', function() {
                this.openInfoWindowHtml("<div id='_blog_"+ blogs[ix] +"' style='width:300px;height:200px;overflow:auto;margin:0;padding:0;'>Loading... " + blogs[ix]+"</div>");
		var iw = map.getInfoWindow();
		ajax_get('/gmaps/blog.php?blog_id='+blogs[ix], renderInfoWindow(blogs[ix]));

        });
        return marker;

} 


function new_draw_blogs(points) {
for(var n=0;n<points.length;n++) {
	if (marker[n]) map.removeOverlay(marker[n]);
		// Somehow - if the point is already drawn - add a second option to view a blog here.
		marker[n] =  newBlogMarker(points[n],n);
		map.addOverlay(marker[n]);
	}
}



function new_draw_points(points) {// Create map version
for(var n=0;n<points.length;n++)
{
if (marker[n]) map.removeOverlay(marker[n]); // clear the old marker...
if (show_points) {
if (n==0) ticon = greenicon
else if (n==points.length-1) ticon=redicon
else ticon=yellowicon
marker[n] = new GMarker(points[n], {icon:ticon, draggable: false, title:'point ' +n});
map.addOverlay(marker[n]);
}
};

}



function new_draw_add_locations(points) {// Create map version
for(var n=0;n<points.length;n++) {
if (marker[n]) map.removeOverlay(marker[n]); // clear the old marker..
if (n == 0) {
marker[n] = currentLocationMarker(points[n],n,geoids[n]);
}
else marker[n] = extra_point(points[n],'Click to add',geoids[n],this_location); // put the location_id and geoid in an array
map.addOverlay(marker[n]);
};

}

function extra_point(point,title,geonameid,parent_id) {
	var marker = new GMarker(point, {icon:greenicon, clickable: true, draggable: false, title:'New Location: '+ title + ' ' +parent_id});
	GEvent.addListener(marker,'click', function() {
                this.openInfoWindowHtml("<div id='_location_"+ geonameid +"' style='width:200px;height:60px;overflow:auto;margin:0;padding:0;font-size:9px;'>Loading... " + parent_id+"</div>"); // TBA
		var iw = map.getInfoWindow();
		ajax_get('/ajax/location_add.php?parent_id='+parent_id+'&geonameid='+geonameid, renderLocationWindow(geonameid));

        });
	return marker;
}

function display_extra_point(title,lat,lng,geonameid,parent_id) {
	var point = new GLatLng(lat,lng);
	if (newmarker) map.removeOverlay(newmarker);
	newmarker = extra_point(point,title,geonameid,parent_id);
	map.addOverlay(newmarker);
}


function new_draw_locations(points) {// Create map version
for(var n=0;n<points.length;n++) {
if (marker[n]) map.removeOverlay(marker[n]); // clear the old marker..
if (n == 0) {
marker[n] = currentLocationMarker(points[n],n,geoids[n]);
}
else marker[n] =  newLocationMarker(points[n],n,geoids[n]); // put the location_id and geoid in an array
map.addOverlay(marker[n]);
};

}

function currentLocationMarker(point,n,location_id) {
        var cmarker = new GMarker(point, {icon:redicon, clickable: false, draggable:true, title:'Current Location: '+ n +' ' +location_id});
	cmarker.enableDragging();
	GEvent.addListener(cmarker,'drag',function() {z++;});
 	GEvent.addListener(cmarker,'dragend',function() {
		var point = cmarker.getPoint();
		ajax_get('/ajax/location_info.php?action=update&location_id='+location_id+'&lat='+point.y+'&lng='+point.x, function() {z++;});
	});
        return cmarker;
} 


function pants() {
       GEvent.addListener(marker,'click', function() {
                this.openInfoWindowHtml("<div id='_location_"+ location_id +"' style='width:200px;height:60px;overflow:auto;margin:0;padding:0;font-size:9px;'>Loading... " + location_id+"</div>"); // TBA
		var iw = map.getInfoWindow();
		ajax_get('/ajax/location_info.php?location_id='+location_id, renderLocationWindow(location_id));

        });
	GEvent.addListener(marker,'dragend',function(point) {
		ajax_get('/ajax/location_info.php?location_id='+location_id+'&lat='+point.y+'&lng='+point.x, renderLocationWindow(location_id));
	});
	marker.enableDragging();

}



function newLocationMarker(point,n,geo_id) {
        var marker = new GMarker(point, {icon:yellowicon, draggable: false, title:'Location: ' +geo_id});
        GEvent.addListener(marker,'click', function() {
                this.openInfoWindowHtml("<div id='_location_"+ geo_id +"' style='width:200px;height:60px;overflow:auto;margin:0;padding:0;font-size:9px;'>Loading... " + geo_id+"</div>"); // TBA
		var iw = map.getInfoWindow();
		ajax_get('/ajax/location_info.php?location_id='+this_location+'&geo_id='+geo_id, renderLocationWindow(geo_id));

        });
        return marker;

} 







// === draw a poly line
function draw() {
//alert('show_line: ' + show_line + ' marker: ' + marker.length); 
poly.length=0;
for(var i=0;i<marker.length;i++) {
        if(line[i]) {map.removeOverlay(line[i])};
        poly.push(marker[i].getPoint());
}
if (show_line) {
        myline = new GPolyline(poly,'#FF0000', 3, 0.7); // to variables later
        //GEvent.addListener(myline,'click', function(point) {alert(closest_point(myline,point));});
        line[i-1]= myline;
        map.addOverlay(line[i-1]);
}
};




// === get the polyline vertix which is closest to the click
function closest_point(myline,point) {
var smallest = 30000000; // 20million m is the longest distance from 0,0
var distance = 0;
var j = 1;
count = myline.getVertexCount();
for(var i=1;i<count;i++) {
        distance = myline.getVertex(i).distanceFrom(point);
        //alert(i+ ': '+ distance +  ' ' + smallest);
        if (distance < smallest) {
                smallest = distance;
                j = i;
        }
}
return j;
}

////zoom to fit

function fit_route(){
var bounds = new GLatLngBounds();
for(var i=0;i<marker.length;i++){bounds.extend(marker[i].getPoint())};
var lngCenter = (bounds.getNorthEast().lng() + bounds.getSouthWest().lng()) / 2;
var latCenter = (bounds.getNorthEast().lat() + bounds.getSouthWest().lat()) / 2;
var center = new GLatLng(latCenter,lngCenter);
map.setCenter(center, map.getBoundsZoomLevel(bounds));
draw();
};

function clear_all() {
for(var i=0;i<marker.length;i++) {
        if(line[i]) {map.removeOverlay(line[i])};
        if (marker[i]) map.removeOverlay(marker[i]);
}
points= new Array();
marker= new Array();
poly= new Array();
line= new Array();
last_point = new GLatLng(0,0);
draw();
}

function remove_last_point() {
        i = marker.length - 1;
        if (line[i]) {map.removeOverlay(line[i]); line.pop();};
        if (marker[i]) {map.removeOverlay(marker[i]);marker.pop();};
        if (poly[i]) {poly.pop();}
        if (points[i]) {points.pop();}

        if (i-1) last_point = marker[i-1].getPoint(); else last_point = new GLatLng(0,0);
        draw();
}


// should be utils...
function dump(arr,level) {
        var dumped_text = "";
        if(!level) level = 0;

        //The padding given at the beginning of the line.
        var level_padding = "";
        for(var j=0;j<level+1;j++) level_padding += "    ";

        if(typeof(arr) == 'object') { //Array/Hashes/Objects
                for(var item in arr) {
                        var value = arr[item];

                        if(typeof(value) == 'object') { //If it is an array,
                                dumped_text += level_padding + "'" + item + "' ...\n";
                                dumped_text += dump(value,level+1);
                        } else {
                                dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
                        }
                }
        } else { //Stings/Chars/Numbers etc.
                dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
        }
        return dumped_text;
}

function debug(obj) {
	//document.getElementById('debug').innerHTML = dump(obj);
}

function displayLatLong(point) {
	if (point) {
                        var x = point.x;
                        var y = point.y;
                } else {
                        var x = map.getCenterLatLng().x;
                        var y = map.getCenterLatLng().y;
                }
                var s = document.getElementById('show');
                s.cX.value = utils_round(x,6);
                s.cY.value = utils_round(y,6);
        }

    
    
function mouse_information(point) {
                if (typeof(point) != 'undefined') {
                        var x = point.x;
                        var y = point.y;
                } else {
                        var x = map.getCenterLatLng().x;
                        var y = map.getCenterLatLng().y;
                }
                if (typeof(last_point) != 'undefined') dist = utils_round(point.distanceFrom(last_point),0);
                else dist = 0;

                //returnDistanceInMiles(x,y,last_point.lng(),last_point.lat()); // KilometerS?
                var s = document.getElementById('mouse_x');
		s.innerHTML = utils_round(x,4);
                var s = document.getElementById('mouse_y');
		s.innerHTML = utils_round(y,4);

		a = normalise_units(dist);
		document.getElementById('mouse_dist').innerHTML = a['distance'];
		document.getElementById('units').innerHTML = a['units'];

        }



function normalise_units(distance) { // in meters
		var units = 'm';
		var a = [];
		a['kilometers'] = utils_round(distance/1000,1);
		a['miles'] = utils_round(distance * 0.000621371192,0);
		a['meters'] = distance;
		
		if (distance > 1000) {
			units = 'km';
			distance = utils_round(distance/1000,1);
		} 
		a['distance'] = distance;
		a['units'] = units;
		
		return a;
	}



 

     


function gmap_icons() {
/*
   	pulseicon = new GIcon();
        pulseicon.image = "/pix/map_icons/pulse.png"; // animated png not supported.
        pulseicon.iconSize = new GSize(30, 30);
        pulseicon.iconAnchor = new GPoint(15, 15);
        pulseicon.infoWindowAnchor = new GPoint(15, 15);
*/

   	blogicon = new GIcon();
        blogicon.image = "/pix/map_icons/blog_entry.png";
        blogicon.shadow = "/pix/map_icons/blog_entry_shadow.png";
        blogicon.iconSize = new GSize(24, 24);
        blogicon.shadowSize = new GSize(24, 24);
        blogicon.iconAnchor = new GPoint(1, 12);
        blogicon.infoWindowAnchor = new GPoint(1, 12);

        diveicon = new GIcon();
        diveicon.image = "/gmaps/icons/dive_flag_18x12.png";
        diveicon.shadow = "/gmaps/icons/dive_flag_shadow_39x12.png";
        diveicon.iconSize = new GSize(18, 12);
        diveicon.shadowSize = new GSize(39, 12);
        diveicon.iconAnchor = new GPoint(1, 11);
        diveicon.infoWindowAnchor = new GPoint(1, 1);


        greenicon = new GIcon();
        greenicon.image = "http://labs.google.com/ridefinder/images/mm_20_green.png";
        greenicon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
        greenicon.iconSize = new GSize(12, 20);
        greenicon.shadowSize = new GSize(22, 20);
        greenicon.iconAnchor = new GPoint(6, 20);
        greenicon.infoWindowAnchor = new GPoint(5, 1);

        redicon = new GIcon();
        redicon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
        redicon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
        redicon.iconSize = new GSize(12, 20);
        redicon.shadowSize = new GSize(22, 20);
        redicon.iconAnchor = new GPoint(6, 20);
        redicon.infoWindowAnchor = new GPoint(5, 1);

        blueicon = new GIcon();
        blueicon.image = "http://labs.google.com/ridefinder/images/mm_20_blue.png";
        blueicon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
        blueicon.iconSize = new GSize(12, 20);
        blueicon.shadowSize = new GSize(22, 20);
        blueicon.iconAnchor = new GPoint(6, 20);
        blueicon.infoWindowAnchor = new GPoint(5, 1);


        yellowicon = new GIcon();
        yellowicon.image = "http://labs.google.com/ridefinder/images/mm_20_yellow.png";
        yellowicon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
        yellowicon.iconSize = new GSize(12, 20);
        yellowicon.shadowSize = new GSize(22, 20);
        yellowicon.iconAnchor = new GPoint(6, 20);
        yellowicon.infoWindowAnchor = new GPoint(5, 1);
}


function utils_round(i,j) {
        // to j decimal places.
        var z = Math.pow(10,j);
        return Math.round(i*z) / z;
}

function map_type_set(map,mapType) {
	if (mapType=='s') {map.setMapType(G_SATELLITE_MAP);}
	else if (mapType=='p') {map.setMapType(G_PHYSICAL_MAP);}
	else if (mapType=='h') {map.setMapType(G_HYBRID_MAP);}
	else {map.setMapType(G_NORMAL_MAP);}
}

function map_type_get(map) {
	if (map.getCurrentMapType()==G_SATELLITE_MAP) {return 's';} 
	else if (map.getCurrentMapType()==G_PHYSICAL_MAP) {return 'p';} 
	else if (map.getCurrentMapType()==G_HYBRID_MAP) {return 'h';} 
	else {return 'm';}
}


function decodeRawPoints(raw_points) {
	var tmp = raw_points.length -2;
	raw_points = raw_points.substr(1,tmp);
	var split_points = raw_points.split('),(');
	var n = split_points.length;
	var i = 0;
	while (i < n && i<1000) { // maximum 100 points.
		var pair = split_points[i].split(',');
		new_add_leg(pair[1],pair[0])
		i++;
	}

}

function save_map() {
	var center_point = map.getCenter();
	var curCenterX = center_point.lng();
	var curCenterY = center_point.lat();

	var zoom_level = new String(map.getZoom());

	var mapType = map_type_get(map);

	document.getElementById("save_title").value = document.getElementById("map_title").value;
	document.getElementById("save_notes").value = document.getElementById("map_notes").value;

	document.getElementById("raw_points").value = points;
	document.getElementById("zoom").value = zoom_level;
	document.getElementById("mapType").value = mapType;
	document.getElementById("X").value = curCenterX;
	document.getElementById("Y").value = curCenterY;
	document.getElementById("way_points").value = show_points;
	document.getElementById("display_line").value = show_line;

	document.saveData.submit();
}



function initialise_map(){
// Standard loadup
	map = new GMap2(document.getElementById("map"));
	map.addControl(new GScaleControl());
   	map.addControl(new GLargeMapControl());
	map.addControl(new GHierarchicalMapTypeControl());
	//GMapTypeControl());
	map.addControl(new GOverviewMapControl());

	map.addMapType(G_PHYSICAL_MAP);
	//map.enableScrollWheelZoom();
	map.enableContinuousZoom();
    	map.setCenter(new GLatLng(14, 14), 2); // World level!
	map.setMapType(G_PHYSICAL_MAP);
	
	gmap_icons();

	GEvent.addListener(map, 'mousemove', function(point) { mouse_information(point);});

 	GEvent.addListener(map, 'click', function(overlay,point) {
       		if (point) {
			new_add_leg(point.x, point.y);
			new_draw_edit_points(points);
			draw();
			//debug(points);
		}
		show_line_info(points);

	});
	GEvent.addListener(map, 'move', function(overlay, point) {
       		if (point) {
			displayLatLong(point);
		}
	});

}


// Legacy functions.

        function encodePolyline(a) {
                var p = a.split(',');
                var d = '';
                var xo=0;
                var yo=0;

                for(c=0;c<p.length;c+=2) {
                        x = p[c];
                        xd = x - xo;
                        xo = x;
                        f = (Math.abs(xd) << 1) - (xd<0);
                        do {
                                e = f & 31;
                                f>>=5;
                                if(f){e|=32};
                                d+=String.fromCharCode(e+63);
                        } while(f!=0);

                        y = p[c+1]
                        yd = y - yo;
                        yo = y;
                        f = (Math.abs(yd)<<1)-(yd<0);

                        do {
                                e = f & 31;
                                f>>=5;
                                if(f){e|=32};
                                d+=String.fromCharCode(e+63);
                        } while (f != 0);
                }

                return d;
        }


        function decodePolyline(a) {
                var b=a.length;
                var c=0;
                var d=new Array();
                var e=0;
                var f=0;
                while(c < b){
                        var g;
                        var h=0;
                        var i=0;
                        do{
                                g=a.charCodeAt(c++)-63;
                                i = i | (g&31)<<h;
                                h = h + 5
                        }while(g>=32);
                        var l;
                        if (i & 1){
                                l = ~(i >> 1);
                        } else {
                                l = i >> 1;
                        }

                        e = e + l;
                        d.push(e);

                        h=0;
                        i=0;
                        do{
                                g=a.charCodeAt(c++)-63;
                                i = i | (g&31)<<h;
                                h = h + 5;
                        }while(g>=32);

                        var m
                        if (i & 1)
                                m = ~(i >> 1);
                        else
                                m = i >> 1

                        f = f + m;
                        d.push(f)
                }
                return d;
        }




        function contractNumber(num) {
                var numObj = new String(num);
                var lenNum = numObj.length;
                var decimalLoc = lenNum-5;
                var afterDecimal = numObj.substr(decimalLoc, 5);
                var beforeDecimal = numObj.substr(0, decimalLoc);
                return beforeDecimal + '.' + afterDecimal;
        }

        function prepPointArray(pointArray){
                var sReturn = '';
                var sIndCoords;
                for (i=0;i<pointArray.length;i++){
                        sReturn += (expandNumber(new String(pointArray[i].y)) + ',' + expandNumber(new String(pointArray[i].x)));
                        if (i<pointArray.length-1)
                                sReturn += ',';
                }
                return sReturn;
        }

	function expandNumber(num) {
                var noMinusNum = num.replace('-','');
                var numDigitsBeforeDot = noMinusNum.indexOf('.');
                num = num.replace('\.','')
                var digitsToGet=numDigitsBeforeDot+5;
                if (num.charAt(0)=="-") {
                        num = num.substr(0,++digitsToGet);
                }else {
                        num = num.substr(0,digitsToGet);
                }
                return num;
        }




