/*
	Start Date	: 04/10/2008
	Author		: Kai Chan, Solid Earth, Inc.
	This is a Google Map API wrapper class.
*/
function SEMapGoogle(mapId, lng, lat, zoom)
{
    this.tileURL = "http://mapmachine.com/SEGTileServer/";
    //this.tileURL = "http://localhost/SEGTileServer/";


    this.map = new GMap2(document.getElementById(mapId));
    
    var longitude = lng;
    var latitude = lat;

    var map = this.map;    
    var tileLayers = new Array();
    var board = "Huntsville";
    var addedLayer = '', addedLayerName = '';
    var bMapInfo;
    var polygonState = 0;
    var circleState = 0;
    var circleLatLng;
    var circleMarker;
    var circleRadius = 0;
    var subjectMarker;
    var statusMarker = [];
    var markerLabel = [];
    var numGrids = -1;
    var showStreetView = true;
    var override;
        
    var grid=[];
    var marker=[];
    var point=[];
    var poly;
    
    var useRuler = false;

    var icon = new GIcon();

    icon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
    icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
    icon.iconSize = new GSize(12, 20);
    icon.shadowSize = new GSize(22, 20);
    icon.iconAnchor = new GPoint(6, 20);
	icon.infoWindowAnchor = new GPoint(7, 2);
	icon.infoShadowAnchor = new GPoint(16, 23);

    map.setCenter(new GLatLng(lat, lng), zoom);
    
    try {
        showStreetView = buttonStreetView;
    } catch(e) {
    }

    try {
        map.addControl(new ExtMapTypeControl({showTraffic: false, showTrafficKey: false, showStreetView: showStreetView, showQuad: false, showEarth: false}));
    } catch(e) {
    
    }

    try {
        map.addControl(new GLargeMapControl3D());
        GScaleControl.prototype.printable = function() { return true }; 
        map.addControl(new GScaleControl());
        //map.addMapType(G_SATELLITE_3D_MAP);
        map.addMapType(G_PHYSICAL_MAP);

	    //this.overViewMap = new GOverviewMapControl();
        //map.addControl(this.overViewMap);
        //this.overViewMap.hide();
    } catch(e) {
    
    }

    addMarker(new GLatLng(-10,-10));
    drawCircle(new GLatLng(-10,-10), 100, 40);
    clearLayers();

    this.longitude = function(lng)
    {
        if (isNaN(lng))
            return longitude;
        else
            longitude = lng;
    }

    this.latitude = function(lat)
    {
        if (isNaN(lat))
            return latitude;
        else
            latitude = lat;
    }
    
    this.setRadius = function(r)
    {
        circleRadius = r;
    }
    
    this.getPolyBounds = function()
    {
        return poly.getBounds();
    }

    this.setAddedLayer = function(l, n)
    {
        addedLayer = l;
        addedLayerName = n;
    }
    
    this.setBoard = function(b)
    {
        board = b;
    }

    this.showStreetView = function(t)
    {
        streetViewButton = t;
    }

    GEvent.addListener(map, "click", 
        function(overlay, latlng) {
            if (bMapInfo) {
                showObj('infoWindow');
                try {
                    document.getElementById('infoWindowText').src = "GetInfo.aspx?b=" + board + '&l=' + addedLayer + '&lon=' + latlng.lng() + '&lat=' + latlng.lat() + "&n=" + addedLayerName;
                } catch(e) {

                }
            } else if (polygonState == 1 && latlng) {
                polygonInit(latlng);
            } else if (polygonState == 2) {
                //polygonState = 1;
                //clearLayers();
                //point = [];
            } else if (circleState == 1 && latlng) {
                circleInit(latlng);
            } else if (circleState == 2) {
                circleState = 3;
                drawCircle(circleLatLng, circleRadius.innerHTML * 1609.344, 80);
                //fit();
            } else if (circleState == 3) {
                clearLayers();
                circleState = 1;
            }
         }
    );
    
    //************************** Circle ****************************
    function circleInit(latlng, noEvent)
    {
        clearLayers();
        addMarker(latlng);
        longitude = latlng.lng();
        latitude = latlng.lat();
        
        if (!noEvent) {
            GEvent.addListener(map, "mousemove", 
                function(latlng) {
                    if (circleState == 2) {
                        clearLayers();
                        addMarker(circleLatLng);
                        //calculate the radius between the center and current mouse cursor
                        var r = circleLatLng.distanceFrom(latlng);
                        circleRadius.innerHTML = roundNumber(r * 0.000621371, 4);
                        drawCircle(circleLatLng, r, 40);
                    }
                 }
            );
            circleState = 2;
        } else {
            circleState = 3;
        }

    }
    
	this.createCircle = function(showDefaultCircle)
	{
        this.clearMarkers();

	    polygonState = 0;
        map.disableDragging();
        
        if (showDefaultCircle) {
            circleInit(subjectMarker.getLatLng(), showDefaultCircle);
            drawCircle(circleLatLng, circleRadius.innerHTML * 1609.344, 80);
            fit();
        } else {
            circleState = 1;
        }
	}

	this.drawCircle = function() {
	    drawCircle(new GLatLng(latitude, longitude), circleRadius.innerHTML * 1609.344, 80);
	}

    function drawCircle(center, radius, nodes, liColor, liWidth, liOpa, fillColor, fillOpa) {
	    //calculating km/degree
	    var latConv = center.distanceFrom(new GLatLng(center.lat()+0.1, center.lng())) * 10;
	    var lngConv = center.distanceFrom(new GLatLng(center.lat(), center.lng()+0.1)) * 10;
	    var step = parseInt(360/nodes)||10;

	    point = [];
	    for(var i=0; i<=360; i+=step) {
	        var pint = new GLatLng(center.lat() + (radius/latConv * Math.cos(i * Math.PI/180)), center.lng() + 
	        (radius/lngConv * Math.sin(i * Math.PI/180)));
	        point.push(pint);
	    }
	    fillColor = fillColor||liColor||"#0055ff";
	    liWidth = liWidth||2;
	    
	    if(poly){map.removeOverlay(poly)};
        poly = new GPolygon(point,liColor,liWidth,liOpa,fillColor,fillOpa);
        
	    map.addOverlay(poly);
	    
        GEvent.addListener(poly, "click", 
            function(latlng) {
                if (bMapInfo) {
                    showObj('infoWindow');
                    try {
                        document.getElementById('infoWindowText').src = "GetInfo.aspx?b=" + board + '&l=' + addedLayer + '&lon=' + latlng.lng() + '&lat=' + latlng.lat() + "&n=" + addedLayerName;
                    } catch(e) {

                    }
                }
             }
        );	    
	    
	    
    }    
    //********************* End Circle *******************************
    
    
    
    //*************************** Polygon ****************************
    function setRulerMiles()
    {
        if (useRuler && point.length >= 2) {
            var d = roundNumber(point[0].distanceFrom(point[1]) * 0.000621371, 4);
            circleRadius.innerHTML = d;
        }    
    }
    
    function polygonInit(latlng)
    {
        if (point.length == 0) {        
            marker = [];
            polygonVertex(latlng);   
            point.push(latlng);

            GEvent.addListener(map, "mousemove", 
                function(latlng) {
                    if (polygonState == 1) {
                        point[point.length-1] = latlng;
                        drawPolygon();
                        setRulerMiles();
                    }
                 }
            );

            GEvent.addListener(marker[0],'click',
                function()
                {
                    if (polygonState == 1) {
                        polygonState = 2;
                        point[point.length - 1] = point[0];
                        drawPolygon();
                    }  
                }
            );
        }
    }
    
	this.createPolygon = function(rulerOnly)
	{
	    useRuler = rulerOnly;
	    this.clearMarkers();
	    polygonState = 1;
	    circleState = 0
        map.disableDragging();
        
        if (useRuler) {
            circleRadius.innerHTML = "0.0";
        }
        
	}
	
	this.clearMarkers = function()
	{
	    clearLayers();	
        point = new Array;
        poly = null;
        marker = [];	
	}
    
    this.redrawPolygon = function(o)
    {
        var i;
        override = o;        
        clearLayers();
        refreshPolygon("#0055ff");

        for (i=0; i<marker.length; i++) {            
            addMarker(marker[i].getPoint());

            GEvent.addListener(marker[i],'drag',function()
            {
                refreshPolygon("#FF0000");
            });

            GEvent.addListener(marker[i],'dragend',function()
            {
                refreshPolygon("#0055ff");
            });

        }
        
    }

    this.drawPolygon = function(pLng, pLat) {
        var lng = pLng.split(",");
        var lat = pLat.split(",");
        var i;

        point = [];
        for (i = 0; i < lng.length; i++) {
            point.push(new GLatLng(lat[i], lng[i]));
        }
        point.push(new GLatLng(lat[0], lng[0]));
        polygonState = 2;
        drawPolygon();
    }

    function drawPolygon(liColor, liWidth, liOpa, fillColor, fillOpa)
    {
        if (point.length > 0) {
	        fillColor = fillColor||liColor||"#0055ff";
	        liWidth = liWidth||2;
            
            if(poly){map.removeOverlay(poly)};
	        poly = new GPolygon(point,liColor,liWidth,liOpa,fillColor,fillOpa);

	        GEvent.addListener(poly, "click", 
	            function(latlng) {
	                polygonVertex(latlng);
	            }
            );

	        map.addOverlay(poly);
	    }
    }
    
    function polygonVertex(latlng)
    {
        if (polygonState == 1 || override) {
            point.push(latlng);
            marker[marker.length] = addMarker(latlng);
            
            GEvent.addListener(marker[marker.length-1],'drag',function()
            {
                refreshPolygon("#FF0000");
            });

            GEvent.addListener(marker[marker.length-1],'dragend',function()
            {
                refreshPolygon("#0055ff");
            });
            
            if (useRuler && point.length == 3) {
                polygonState = 2;
            }
        }    
    }
    
    function refreshPolygon(fillColor)
    {    
        var i;

        try {
            if (marker.length > 0) {
                for (i=0; i<marker.length; i++) {
                    point[i] = marker[i].getPoint();            
                }
                point[marker.length] = marker[0].getPoint();
            }
            map.removeOverlay(poly);
	        poly = new GPolygon(point,null,2,null,fillColor);
            map.addOverlay(poly);
            
            setRulerMiles();
       } catch(e) {
       }

    }

    this.polygonLongitude = function()
    {
        var lng = roundNumber(point[1].lng(), 6);
        var i;
        
        for (i=2;i<point.length;i++) {
            lng += ',' + roundNumber(point[i].lng(), 6);
        }
        
        return lng;
    }
    
    this.polygonLatitude = function()
    {
        var lat = roundNumber(point[1].lat(), 6);
        var i;
        
        for (i=2;i<point.length;i++) {
            lat += ',' + roundNumber(point[i].lat(), 6);
        }
        
        return lat;
    }
    
    this.addGrid = function(lat1, lng1, lat2, lng2, color)
    {
        numGrids++;

        grid[numGrids] = new GPolygon([
            new GLatLng(lat1, lng1),
            new GLatLng(lat2, lng1),
            new GLatLng(lat2, lng2),
            new GLatLng(lat1, lng2),
            new GLatLng(lat1, lng1)
        ], color, 1, 1, color, 0.7);

        map.addOverlay(grid[numGrids]);
    }

    this.clearGrids = function()
    {        
        while (numGrids >= 0)
        {
            map.removeOverlay(grid[numGrids]);
            numGrids--;
        }
    }
    //********************* End Polygon ******************************
    
    this.refresh = function()
    {
        map.checkResize();
    }
    
    this.getBoundLngLat = function()
    {
        var sw = map.getBounds().getSouthWest();
        var ne = map.getBounds().getNorthEast();
        
        return "lng1=" + roundNumber(sw.lng(), 6) + "&lat1=" + roundNumber(sw.lat(), 6) + "&lng2=" + roundNumber(ne.lng(), 6) + "&lat2=" +  roundNumber(ne.lat(), 6);
    }

    this.setBound = function(lng, lat) {
        if (lng.length > 0) {
            var bounds = new GLatLngBounds();
            var i;
            var point;

            for (i = 0; i < lng.length; i++) {
                if (parseFloat(lng[i]) < 0) {
                    point = new GLatLng(lat[i], lng[i]);
                    bounds.extend(point);
                }
            }

            map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
        }
    }

    function addMarker(p)
    {
        var marker = new GMarker(p, {icon:icon, draggable: true});
        circleLatLng = p;
        map.addOverlay(marker);
        
        return marker;
    }

	this.createMarker = function(lng, lat)
	{
	    var p = new GLatLng(lat, lng)
        var marker = new GMarker(p, {icon:icon, draggable: false});
        map.addOverlay(marker);
	}
	
	this.clearStatusMarkers = function()
	{
	    var i;
	    
	    for (i=0; i<statusMarker.length; i++) {
	        map.removeOverlay(statusMarker[i]);
	        map.removeOverlay(markerLabel[i]);
        }
        
        statusMarker = [];
        markerLabel = [];
	}

	this.addStatusMarker = function(id, lng, lat, info, status)
	{	        
	    //var marker;
	    var house = new GIcon(icon);
	    var i = '';
	    var ln = map.getBounds().getNorthEast().lng() - 0.0074;
	    var la = map.getBounds().getSouthWest().lat() - 0.0026;
	    var pt = new GLatLng(la, ln);

	    if (status)
	        i = '_' + status;

	    house.image = "Images/marker_house" + i + ".gif";
	    statusMarker[id - 1] = new GMarker(new GLatLng(lat, lng), { icon: house, draggable: false, title: id });

	    if (info != '') {
	        GEvent.addListener(statusMarker[id - 1], "mouseover", function(latlng) {
	            //map.openInfoWindowHtml(pt, info, {suppressMapPan: true, maxHeight: 230, maxWidth: 210});
	            showObj('divInfo');
	            document.getElementById('divInfo').innerHTML = "<a href=javascript:hideObj('divInfo') title='Close'><img src='images/menu_picker_close_off.gif' border=0 /></a>&nbsp;<font size=1>" + info + "</font>";
	        }
            );
	    }

	    map.addOverlay(statusMarker[id - 1]);

	    // show the id
	    markerLabel[id - 1] = new ELabel(new GLatLng(lat, lng), '<div style="background-color:#ffffcc;border:1px solid black;font-size:10">' + id + '<\/div>', null, new GSize(5, -15));
	    map.addOverlay(markerLabel[id - 1]);
	}
	
this.createButton = function(text) {
  var buttonDiv = document.createElement("div");
  this.setButtonStyle_(buttonDiv);
  buttonDiv.style.cssFloat = "left";
  buttonDiv.style.styleFloat = "left";
  var textDiv = document.createElement("div");
  textDiv.appendChild(document.createTextNode(text));
  textDiv.style.width = "6em";
  buttonDiv.appendChild(textDiv);
  return buttonDiv;
}

this.setButtonStyle_ = function(button) {
  button.style.color = "#000000";
  button.style.backgroundColor = "white";
  button.style.font = "small Arial";
  button.style.border = "1px solid black";
  button.style.padding = "0px";
  button.style.margin= "0px";
  button.style.textAlign = "center";
  button.style.fontSize = "12px"; 
  button.style.cursor = "pointer";
}
	
	
	this.addHouseMarker = function(lng, lat, info, drag)
	{
		var house = new GIcon(icon);
		
		house.image = "Images/marker_house.gif";

        if (subjectMarker)
            map.removeOverlay(subjectMarker);

		subjectMarker = new GMarker(new GLatLng(lat, lng), {icon:house, draggable: drag, dragCrossMove: true});

  		GEvent.addListener(subjectMarker, "click", function(latlng) {
			    if (circleState == 1) {
  		            circleInit(latlng);
			    } else if (polygonState == 1) {
                    polygonInit(latlng);
			    }
			}
		);
		
		//allow user to drag the subject around
		if (drag) {
            GEvent.addListener(subjectMarker, "dragstart", function() {
                map.closeInfoWindow();
            }); 

            GEvent.addListener(subjectMarker, "dragend", function(latlng) {
                longitude = latlng.lng();
                latitude = latlng.lat();
            });                        
        } else {
        //1/18/2010 - commented out: this crash on IE7 in an iframe.
        /*
  		    GEvent.addListener(subjectMarker, "mouseover", function(latlng) {
  		            if (circleState + polygonState == 0) {
			            subjectMarker.openInfoWindowHtml('<font size=2>' + info + '</font>');  
			        }
			    }
		    );
		    */
		}
		
		map.addOverlay(subjectMarker);

		return subjectMarker;
	}

    function clearLayers()
    {
        map.clearOverlays();
        if (subjectMarker)
            map.addOverlay(subjectMarker);
    }
    
    this.clearVertexes = function()
    {
        var i;
        var n = marker.length;

        for (i=n-1; i>=0; i--) {
            map.removeOverlay(marker[i]);
        }
    }
    
    this.clearProximity = function()
    {
        clearLayers();
	    polygonState = 0;
	    circleState = 0        
        point=[];
        marker=[];
        poly = null;
    }
    
    ////////change color of the line
    function color(rgb)
    {
        if(line) {
            line.color=rgb;
            line.redraw(true);
        }
    }

    this.setGetInfo = function(on)
    {
        bMapInfo = on;
        if (on) {
            this.map.disableDragging();
        } else {
            this.map.enableDragging();
        }        
    }

    this.getMapURL = function() {
        var url = "cx=" + map.getCenter().lng() + "&cy=" + map.getCenter().lat() + "&zoom=" + map.getZoom() +
            "&type=" + map.getCurrentMapType().getName();

        if (subjectMarker) {
            url += "&sx=" + subjectMarker.getLatLng().lng() + "&sy=" + subjectMarker.getLatLng().lat();
        }

        if (listData != "") {
            url += "&use=data&action=list&mls=" + URLEncode(listData);
        } else if (mapAction == "list")
            url += "&use=list&mls=" + mls;
        else
            url += "&use=u";

        return url;
    }

    function URLEncode(data) {
        // The Javascript escape and unescape functions do not correspond
        // with what browsers actually do...
        var SAFECHARS = "0123456789" + 				// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + // Alphabetic
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()"; 				// RFC2396 Mark characters
        var HEX = "0123456789ABCDEF";

        var encoded = "";
        for (var i = 0; i < data.length; i++) {
            var ch = data.charAt(i);
            if (ch == " ") {
                encoded += "+"; 			// x-www-urlencoded, rather than %20
            } else if (SAFECHARS.indexOf(ch) != -1) {
                encoded += ch;
            } else {
                var charCode = ch.charCodeAt(0);
                if (charCode > 255) {
                    alert("Unicode Character '"
                        + ch
                        + "' cannot be encoded using standard URL encoding.\n" +
				          "(URL encoding only supports 8-bit characters.)\n" +
						  "A space (+) will be substituted.");
                    encoded += "+";
                } else {
                    encoded += "%";
                    encoded += HEX.charAt((charCode >> 4) & 0xF);
                    encoded += HEX.charAt(charCode & 0xF);
                }
            }
        } // for

        return encoded;
    };
    
    
    this.getSubjectLng = function()
    {
        return subjectMarker.getLatLng().lng();
    }
    
    this.getSubjectLat = function()
    {
        return subjectMarker.getLatLng().lat();
    }

    this.setMapURL = function(url)
    {
    
    }

    this.addKMLLayer = function(layer) {    
        var geoXml = new GGeoXml(this.tileURL.replace("SEGTileServer", "KML") + board + "/" + layer);
        map.addOverlay(geoXml);

        tileLayers[layer] = geoXml;        
    }

    this.removeKMLLayer = function(layer)
    {
        map.removeOverlay(tileLayers[layer]);    
    }

    this.addTileLayer = function(layer, i)
    {
        var tileURL = this.tileURL;
    
        this.customGetTileUrl = function(tile, z)
        {
            var quadKey = "";
            var digit;
            var mask;
            var i;
            
            for (i=z; i>=1; i--) {
                digit = 0;
                mask = Math.pow(2, i-1);

                if ((tile.x & mask) != 0) {
                    digit++;
                }
                if ((tile.y & mask) != 0) {
                    digit++;
                    digit++;
                }
                
                quadKey += digit;
            }
            
            //prompt("url", tileURL + board + "/" + layer + "/" + quadKey + ".gif");
            return tileURL + board + "/" + layer + "/" + quadKey + ".gif";
        }

        // Set up the copyright information
        // Each image used should indicate its copyright permissions
        var myCopyright = new GCopyrightCollection("(c) ");
        myCopyright.addCopyright(new GCopyright(layer,
          new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180)), 0, '©2008 Solid Earth, Inc.'));

        var tilelayer = new GTileLayer(myCopyright);
        tilelayer.getTileUrl = this.customGetTileUrl;

        var myTileLayer = new GTileLayerOverlay(tilelayer);
        this.map.addOverlay(myTileLayer);
        
        tileLayers[layer] = myTileLayer;
    }
    
    this.removeTileLayer = function(layer)
    {
        map.removeOverlay(tileLayers[layer]);
    }
    
	this.getZoom = function()
	{
		return map.getZoom();
	}

	this.getX = function()
	{
		return map.getCenter().lng();
	}
	
	this.getY = function()
	{
		return map.getCenter().lat();
	}

	this.setZoom = function(z)
	{
		map.setZoom(z);
	}

	this.setCenter = function(x, y) {
	    map.panTo(new GLatLng(y, x));
	}

	this.setSubjectCenter = function(p, z) {
	    longitude = p.lng();
	    latitude = p.lat();

	    map.setCenter(p, z);
	}

    function roundNumber(number,decimal_points) {
	    if(!decimal_points) return Math.round(number);
	    if(number == 0) {
		    var decimals = "";
		    for(var i=0;i<decimal_points;i++) decimals += "0";
		    return "0."+decimals;
	    }

	    var exponent = Math.pow(10,decimal_points);
	    var num = Math.round((number * exponent)).toString();
	    return num.slice(0,-1*decimal_points) + "." + num.slice(-1*decimal_points)
    }
    
    function fit()
    {
        var bounds = new GLatLngBounds();
        for(var i=0;i<point.length;i++){bounds.extend(point[i])};
        var center = bounds.getCenter();
        map.setCenter(center, map.getBoundsZoomLevel(bounds));
    }

    
}

