// ----------------- BEGIN REQUIRED INTERFACE METHODS --------------------//
var SE_PreLoadTest_VMap = 1;
function VInitMap() {
    if (typeof (__pageTimer) != 'undefined') __pageTimer.addTime("VInitMap top");
    var latLon = new VELatLong(this.centerPoint.latitude, this.centerPoint.longitude);
    var mapStyle = VEConvertMapStyle(this.mapType);

    // zoom level 1- is world view, 17 is max match w/google, 19 is absolute max zoom)
    var zoom = 17 - this.zoomLevel;
    
    var mode = VEMapMode.Mode2D;
    var fixed = false;
    var showModeSwitch = true;
    var tileBuffer = 1;

    this.map = new VEMap(this._mapDiv.id);
    this.map.AttachEvent("onstartpan", _SEMap_OnStartPan);
    this.map.AttachEvent("onstartzoom", _SEMap_OnStartZoom);
    var seMap = this;
    this.map.AttachEvent("onendzoom", function(){ VUpdateView(seMap)});
    this.map.AttachEvent("onchangemapstyle", function(){ VUpdateView(seMap)});
    var showDashboard = true;
    // SetDashboardSize must be called before calling LoadMap
    switch (this.controlSize) {
        case "none":
            showDashboard = false;
            break;
        case "small":
            this.map.SetDashboardSize(VEDashboardSize.Tiny);
            break;
        case "normal":
            this.map.SetDashboardSize(VEDashboardSize.Small);
            break;
        case "large":
            this.map.SetDashboardSize(VEDashboardSize.Normal);
            break;
    }
    
    this.map.LoadMap(latLon, zoom, mapStyle, fixed, mode, showModeSwitch, tileBuffer);

    if (showDashboard)
        this.map.ShowDashboard();
    else
        this.map.HideDashboard();

    this.map.Hide3DNavigationControl();
    this._mapDiv.onmousemove = _SEMap_MouseMoveHandler;
    var mapid = this.clientID;
    $(window).scroll(function() { SEMap_OnScroll(mapid); });

    this.map.AttachEvent("onmouseover", VDisableInfoBox);
    this.map.AttachEvent("onmousedown", VCustomDragZoom);
    this.map.DeleteAllShapes();
    this.map.DeleteAllShapeLayers();
    this._drawShapeLayer = null;
    this.pushpinShapeLayer = new VEShapeLayer();
    this.map.AddShapeLayer(this.pushpinShapeLayer);
    
    this.pushpinShapes = new Array();
    var seMap = this;
    VUpdateView(seMap);
}

function VEConvertMapStyle(mapType) {
    var mapStyle = VEMapStyle.Road;
    if (mapType == "aerial")
    { mapStyle = VEMapStyle.Aerial; }
    else if (mapType == "oblique")
    { mapStyle = VEMapStyle.Oblique; }
    else if (mapType == "hybrid")
    { mapStyle = VEMapStyle.Hybrid; }
    else if (mapType == "birdseye")
    { mapStyle = VEMapStyle.Birdseye; }
    else if (mapType == "birdseyehybrid")
    { mapStyle = VEMapStyle.BirdseyeHybrid; }
    return mapStyle
}
function VCustomDragZoom(e) {
    if (e.altKey || e.middleMouseButton) {
        var seMap = VDragZoomGetMap();
        seMap.dragZoomStart(e);
        return true;
    }
}

function VUpdateView(map) {

     VGetMapView(map)
     SEMap.ClosePopups();
}

function VGetMapView(map)
{
    if(!map)
        map = SEMap_GetCurrentMap();
    if (map) {
        map._originalMapView = map.map.GetMapView();
    }   
}

function VDisableInfoBox(e) {
    if (e.elementID)
        return true;
}
function VPanMap(direction, xDelta, yDelta, onEndPanCallback) {
    if (onEndPanCallback) {
        this._onEndPanCallBack = onEndPanCallback;
        this.map.AttachEvent("onendpan", onEndPanCallback);
        this._isPanning = true;       
    }
    switch (direction) {
        case "down":
            this.map.Pan(0, (this._mapDiv.clientHeight * this.panFraction));
            break;
        case "up":
            this.map.Pan(0, -(this._mapDiv.clientHeight * this.panFraction));
            break;
        case "left":
            this.map.Pan(-(this._mapDiv.clientWidth * this.panFraction), 0);
            break;
        case "right":
            this.map.Pan((this._mapDiv.clientWidth * this.panFraction), 0);
            break;
        case "":
            this.map.Pan(-parseInt(xDelta), parseInt(yDelta));
            break;
    }
    setTimeout('VClearEndPanCallback(' + this.id + ')', 2000);
}

function VClearEndPanCallback(myMap) {

    if (myMap._onEndPanCallBack && typeof (myMap._onEndPanCallback) != 'undefined') {
        myMap.map.DetachEvent("onendpan", myMap.onEndPanCallback);
        myMap._onEndPanCallBack = null;
    }
    myMap._isPanning = false;
}

function VSetCenterZoom(centerPoint, zoomLevel) {
    var oldZoom = this.zoomLevel;
    this.centerPoint = centerPoint;
    this.zoomLevel = zoomLevel;
    if (_SEMap_IsValidLatLong(centerPoint.latitude, centerPoint.longitude)) {
        this.map.SetCenterAndZoom(new VELatLong(centerPoint.latitude, centerPoint.longitude), 17 - zoomLevel);
        if (_SEMap_UserAgent('firefox') && (Math.abs(this.getBounds().northWest.latitude - centerPoint.latitude) < .001)) {
            // VirtualEarth/Firefox 1.5 bug - doesn't set latitude correctly
            this.map.Pan(0, -(this._mapDiv.clientHeight * .5));
        }
        if (oldZoom == zoomLevel)
            this.functionToCallOnPan();
    }
    VUpdateView(this);
}

function VClearMarkers() {
    if (this.map) {
        if (this.pushpinShapeLayer) this.pushpinShapeLayer.DeleteAllShapes();
        this.pushpinShapes = new Array();
    }
}

SEMap.prototype.addPushpins = function (pushpins) {
    //problems using the existing array directly so - create a new one
    var pushpins = new Array();
    for (var i = 0; i < this.markers.length; i++) {
        pushpins.push(this.pushpinShapes[this.markers[i].markerId]);
    }
        
    var oldMapType = null;
    if (this.mapType == "birdseyehybrid") {
        oldMapType = this.mapType;
        this.map.SetMapStyle(VEConvertMapStyle("road"));
    }
    this.pushpinShapeLayer.AddShape(pushpins);

    if (oldMapType != null)
        this.map.SetMapStyle(VEConvertMapStyle(oldMapType));    
}

function VSetBestMapView(bounds) {
    if (typeof (__pageTimer) != 'undefined') __pageTimer.addTime("VSetBestMapView 1");
    var boundsPoints = new Array();
    boundsPoints.push(new VELatLong(bounds.northWest.latitude, bounds.northWest.longitude));
    boundsPoints.push(new VELatLong(bounds.southEast.latitude, bounds.southEast.longitude));
    this.map.SetMapView(boundsPoints);
    
    this.zoomLevel = 17 - this.map.GetZoomLevel();
    this.centerPoint.latitude = (bounds.northWest.latitude + bounds.southEast.latitude) / 2;
    this.centerPoint.longitude = (bounds.northWest.longitude + bounds.southEast.longitude) / 2;
    if (typeof (__pageTimer) != 'undefined') __pageTimer.addTime("VSetBestMapView 2");
}

function VGetBounds() {
    var southEastLL = new VELatLong();
    var northWestLL = new VELatLong();
    if (this.map) {
        var mapView = null;
        try {        
            mapView = this.map.GetMapView();
        }
        catch (e) { }

        if (mapView) {
            southEastLL = mapView.BottomRightLatLong;
            northWestLL = mapView.TopLeftLatLong;
        }

    }
    if (northWestLL.Latitude)
        return new SEBounds(new SEPoint(northWestLL.Latitude, northWestLL.Longitude),
		        new SEPoint(southEastLL.Latitude, southEastLL.Longitude));
    else
        return new SEBounds(new SEPoint(), new SEPoint());

}

function VGetCenter() {
    var centerLL =  new SEPoint(0,0);
    if (this.map) {
        var ctr = this.map.GetCenter();
        centerLL = new SEPoint(ctr.Latitude, ctr.Longitude);
    }
    return centerLL;
}

function VAddMoveResizeEvents() {
    this.map.AttachEvent("onendpan", this.functionToCallOnZoom);
    this.map.AttachEvent("onendzoom", this.functionToCallOnZoom);
    this.map.AttachEvent("onendcontinuouspan", this.functionToCallOnPan);
}

var VResizeTimeoutId = -1;
function VResize() {
    
    if (_SEMap_UserAgent("gecko"))
        VDoResize(this);
    else
        VResizeTimeoutId = setTimeout('VDoResize(' + this.id + ')', 100);
}
var VEResizeCount = 0;
function VEResetResizeCount() {
    VEResizeCount = 0;
}
function VDoResize(map) {
    if (map) {
        map._mapDiv.style.width = "100%";
        var width
        var height
        if (document.getElementById(map.id.replace("_map", "_td"))) {
            width = $("#" + map.id.replace("_map", "_td")).availableWidth();
            height = $("#" + map.id.replace("_map", "_td")).availableHeight() -6;
        }
        else {
            var widthParent = map._mapDiv.parentElement
            while (widthParent.offsetWidth == 0 && widthParent.parentElement)
                widthParent = widthParent.parentElement;

            if (widthParent.currentStyle && widthParent.currentStyle.width && widthParent.currentStyle.width.indexOf("px") != -1)
                width = widthParent.currentStyle.width.replace("px", "");
            else
                width = widthParent.offsetWidth;

            var heightParent = map._mapDiv.parentElement
            while (heightParent.offsetWidth == 0 && heightParent.parentElement)
                heightParent = heightParent.parentElement;

            if (heightParent.currentStyle && heightParent.currentStyle.height && heightParent.currentStyle.height.indexOf("px") != -1)
                height = heightParent.currentStyle.height.replace("px", "");
            else
                height = heightParent.offsetHeight;
        }

        width = parseInt(width);
        height = parseInt(height);
        
        if (map.map && width > 10 && height > 10) {
            if (VEResizeCount < 5) {

                map._mapDivWidth =  width - 2
                map._mapDivHeight =  height - 2
                if (SE_MSIEVersion() == 6)
                {
                    map._mapDivWidth -= 4;
                    map._mapDivHeight -= 4;
                }
                map.map.Resize(map._mapDivWidth, map._mapDivHeight);
                
                VEResizeCount++;
                setTimeout(VEResetResizeCount, 3000);
            }            
        }
    }
}

SEMarker.prototype.loadMarkerDivText = function (text) {
    var puDiv = this.$popupDiv[0];
    if (puDiv && puDiv.isPopup && text && text.length > 0) {
        var contentHTML = "<table border=0 id='" + this.createMarkerID(puDiv.markerIndex) + "_table' class=PopupTable cellpadding=0 cellspacing=0>"
				+ "<tr><td>"
				+ text
				+ "</td></tr>"
				+ "</table>";
        puDiv.contentCell.innerHTML = contentHTML;
        return true;
    }
    return false;
}

function VAddPushpin(markerIndex, marker, zIndex, tooltipHtml) {

    var icon = marker.getIcon();
    var markerId = marker.markerId;
   	
    var onClick = "";
    var onMouseOver = "";
    var onMouseOut = "";
    if (this.enableMouseOverHighlight) {
        onMouseOver = this.id + ".highlightPushpin('" + markerIndex + "', true, 'notpopup');";
        if (this.mouseOverAction == "nothing")
            onMouseOut = " setTimeout('" + this.id + ".highlightPushpin(" + markerIndex + ", false, _SEMap_Popup)'," + this.closePopupAfter + "); ";
    }
    switch (this.mouseOverAction) {
        case "popup":
            onMouseOver = onMouseOver + this.id + ".openPopup(" + markerIndex + ", " + this.closePopupAfter + ");";
            onMouseOut = onMouseOut + "if(_SEMap_CurrentPopupDiv){clearTimeout(_SEMap_CurrentPopupDiv.closeTimeoutId);_SEMap_CurrentPopupDiv.closeTimeoutId=setTimeout('_SEMap_CloseDiv(' + _SEMap_CurrentPopupDiv.id + ',false)', " + this.closePopupAfter + ");}";
            break;
        case "tooltip":
            onMouseOver = onMouseOver + this.id + ".showTooltip(" + markerIndex + ", " + this.closePopupAfter + ")";
            onMouseOut = onMouseOut + "if(_SEMap_CurrentTooltipDiv){clearTimeout(_SEMap_CurrentTooltipDiv.closeTimeoutId);_SEMap_CurrentTooltipDiv.closeTimeoutId=setTimeout('_SEMap_CloseDiv(' + _SEMap_CurrentTooltipDiv.id + ',false)', " + this.closePopupAfter + ");}";
            break;
    }
    if (this.enableClickPopup)
        onClick = " onmousedown=\"" + this.id + ".openPopup(" + markerIndex + ", " + this.closePopupAfterClick + ");\"";

    onMouseOver = " onmouseover=\"" + onMouseOver + "\"";
    onMouseOut = " onmouseout=\"" + onMouseOut + "\"";
    var pushpinHtml = "<img src='" + icon.src + "' id='" + markerId + "_img' border=0 "
				+ onClick + " " + onMouseOver + " " + onMouseOut + " status=''/>";


    var pushpinHtml1 = "<DIV id='" + markerId + "pp' style='background-color:transparent;width:20px;' >\n"
			+ pushpinHtml
			+ "</DIV>";    
    var pushpin = new VEShape(VEShapeType.Pushpin, new VELatLong(marker.location.latitude, marker.location.longitude));   
    pushpin.SetCustomIcon(pushpinHtml1);
    
    this.pushpinShapes[markerId] = pushpin;
    pushpin.SetZIndex(zIndex);
    var divTooltip = document.createElement("DIV");
    divTooltip.id = markerId + "_tooltip";
    divTooltip.style.position = "absolute";
    divTooltip.style.display = "none";
    divTooltip.className = "tooltip";
    divTooltip.innerHTML = tooltipHtml;
    this._mapDiv.parentElement.insertBefore(divTooltip, this._mapDiv);
    marker.$tooltipDiv = $(divTooltip);
    marker.prepPopupDiv(markerIndex, this.closePopupAfter, "_tooltip");

    var divPopup = document.createElement("DIV");
    divPopup.id = markerId + "_popup";
    divPopup.style.position = "absolute";
    divPopup.style.display = "none";
    divPopup.innerHTML = "";
    divPopup.style.zIndex = _SEMap_PopupZIndex;
    marker.$popupDiv = $(divPopup);
    this._mapDiv.parentElement.insertBefore(divPopup, this._mapDiv);
    marker.prepPopupDiv(markerIndex, this.closePopupAfter, "_popup");
}


SEMarker.prototype.prepPopupDiv = function (markerIndex, closePopupAfter, typeSuffix) {

    var puDiv = this.getPopupDiv(typeSuffix);
    puDiv.close = this.map.closeDiv;
    puDiv.closePopupAfter = closePopupAfter;

    puDiv.map = this.map;
    puDiv.marker = this;
    puDiv.markerIndex = markerIndex;
    puDiv.marker.setZIndex(_SEMap_PopupZIndex);
    puDiv.offsetBottom = 5;
    puDiv.offsetRight = 5;
    var icon = puDiv.marker.getIcon();
    puDiv.effectiveImageWidth = icon.width / 2 - puDiv.offsetRight;
    puDiv.effectiveImageHeight = icon.height / 2 - puDiv.offsetBottom;

    puDiv.isloaded = typeSuffix != "_popup"
    puDiv.style.width = null;

    if (typeSuffix == "_popup") {
        puDiv.innerHTML = "";
        puDiv.className = 'PopupDiv';
        puDiv.isShowing = false;
        puDiv.margin = 15;
        puDiv.popupTable = document.getElementById("tbPopup").cloneNode(true);
        puDiv.popupTable.id = this.markerId + "_table";
        puDiv.appendChild(puDiv.popupTable);
        puDiv.contentCell = SEMap_FindChildNode(puDiv.popupTable, puDiv.map.id.replace("_map", "_popupContent"));
    }
    else {
        puDiv.margin = 5;
        puDiv.popupTable = document.getElementById(this.markerId + "_ttDiv");
        puDiv.contentCell = null;
    }
}
        

SEMarker.prototype.highlightIcon = function () {
    var marker = this;
    pushpinImg = document.getElementById(this.markerId + '_img');
    if (pushpinImg) {
        marker.setZIndex(_SEMap_TooltipZIndex);
        if (_SEMap_CurrentPopupDiv && _SEMap_CurrentPopupDiv.markerIndex != marker.markerIndex)
            _SEMap_CurrentPopupDiv.marker.setZIndex(_SEMap_PopupZIndex);
        marker.changeIconSrc(pushpinImg, marker.getSelectedIcon().src, marker.markerIndex);
    }
}

SEMarker.prototype.unHighlightIcon = function () {
    var pushpinImg = document.getElementById(this.markerId + '_img');
    var icon = this.getIcon();
    if (pushpinImg) {
        if (!_SEMap_IsSameUrl(pushpinImg.src, icon.src)) {
            if (!_SEMap_CurrentPopupDiv 
                || _SEMap_CurrentPopupDiv.markerIndex != this.markerIndex) {

                this.changeIconSrc(pushpinImg, icon.src, this.markerIndex);
                this.setZIndex(_SEMap_BaseZIndex);
            }
            else
                this.setZIndex(_SEMap_PopupZIndex);
        }
    }
}

SEMarker.prototype.changeIconSrc = function (pushpinImg, newSrc, markerIndex) {
    if (pushpinImg && pushpinImg.src) {
        if (!_SEMap_IsSameUrl(pushpinImg.src, newSrc)) {
            var markerID = this.map.createMarkerID(markerIndex);
            var ppShape = this.map.pushpinShapes[markerID];
            var currentIcon = ppShape.GetCustomIcon();
            var re = new RegExp(/<img.*src=[\'\"]?([^\'\" ]*)[\'\"]? .*>/i);
            var aMatches = re.exec(currentIcon);
            if (aMatches.length > 1) {
                var newIcon = currentIcon.replace(aMatches[1], newSrc);
                ppShape.SetCustomIcon(newIcon);
            }
            pushpinImg.src = newSrc;
        }
    }
}

SEMarker.prototype.setZIndex = function (zIndex) {
    if (this.map.pushpinShapes[this.markerId].GetZIndex() != zIndex)
        this.map.pushpinShapes[this.markerId].SetZIndex(zIndex);
}

function VOpenBirdsEyePopup(sDiv) {
    var puDiv = document.getElementById(sDiv);
    if (puDiv.marker.htmlBirdsEyeDetailUrl == "")
        puDiv.marker.htmlBirdsEyeDetailUrl = puDiv.marker.htmlPageUrl;
    var url = "/Common/SEMapping/ObliquePopup.aspx"
			+ "?latitude=" + puDiv.marker.location.latitude
			+ "&longitude=" + puDiv.marker.location.longitude
			+ "&sourceApp=" + puDiv.map.sourceApp
			+ "&detailPath=" + escape(puDiv.marker.htmlBirdsEyeDetailUrl 
			+ (puDiv.marker.htmlBirdsEyeDetailUrl.toLowerCase().indexOf('sourceapp') == -1 ? "&sourceapp=" + puDiv.map.sourceApp : ""));

    var mPopup = window.open(url, puDiv.markerId,
				'fullscreen=0' +
				',toolbar=0' +
				',status=0' +
				',statusbar=0' +
				',menubar=0' +
				',scrollbars=1' +
				',resizable=1' +
				',directories=0' +
				',location=0' +
				',width=800' +
				',top=100' +
				',left=100' +
				',height=600'
			);
    mPopup.focus();
}



function VGetXY(myPosition) {
    var xy = this.map.LatLongToPixel(new VELatLong(myPosition.latitude, myPosition.longitude));
    xy.x = parseInt(xy.x);
    xy.y = parseInt(xy.y);

    return xy;
}

function VMap_GetMapDimensions() {
    VGetMapView(this);
    var originalXY = this.map.LatLongToPixel(this._originalMapView.TopLeftLatLong);

    this._mapDivOffsetX = parseInt(originalXY.x);
    this._mapDivOffsetY = parseInt(originalXY.y);
}

function VDrawPolyline() {
}

function VAttachEvent(eventname, functionObject) {
    this.map.AttachEvent(eventname, functionObject);
}
function VDetachEvent(eventname, functionObject) {
    this.map.DetachEvent(eventname, functionObject);

}
function VDisableDragging() {
    // this appears to be a MSVE bug - it doesn't seem to stop the dragging
    //this.map.SetAnimationEnabled(false)
}
function VEnableDragging() {
    //this.map.SetAnimationEnabled(true)
}

function VAttachMouseEvents() {
}
function VDetachMouseEvents() {
}

function VSetForPrint() {
    var pOptions = new VEPrintOptions(true);
    this.map.SetPrintOptions(pOptions);
}
function VHideScaleBar() {
    this.map.HideScalebar();
}

function VIncludePointInView(seLatLong) {
    return false;
    //	   var thisMapView = this.map.GetMapView();
    //	    if (seLatLong.latitude > thisMapView.TopLeftLatLong.Latitude
    //	        || seLatLong.latitude < thisMapView.BottomRightLatLong.Latitude
    //	        || seLatLong.longitude < thisMapView.TopLeftLatLong.Longitude
    //	        || seLatLong.longitude > thisMapView.BottomRightLatLong.Longitude)
    //	        {
    //	            this.map.PanToLatLong(new VELatLong(seLatLong.latitude, seLatLong.longitude));
    //	            return true;
    //	         }
    //	         return false;
}

// ----------------- END REQUIRED INTERFACE METHODS --------------------//



function VLatLngFromPixel(map, x, y) {
    var myLocation = new VEPixel(x, y);
    if (map.GetMapStyle() != null)
        return map.PixelToLatLong(myLocation);
    return null;
}

function VGetZoomLevel() {
    return 17 - this.map.GetZoomLevel();
}

function VShowXY(e) {
    alert("Clicked point=" + semapVirtualEarth_map.map.GetX(e.view.latlong.longitude) +
			", " + semapVirtualEarth_map.map.GetY(e.view.latlong.latitude));
}


function VGetDashboard() {
    if (!this.dashboard) {
        this.dashboard = new SEMap_Dashboard();
        this.dashboard.div = SE_FindChildNodeByClass(this._mapDiv, "Dashboard", true);
    }

    if (this.dashboard.div) {
        if (!this.dashboard.width) this.dashboard.width = this.dashboard.div.offsetWidth;
        if (!this.dashboard.height) this.dashboard.height = this.dashboard.div.offsetHeight;

        this.dashboard.top = this.dashboard.div.offsetTop;
        this.dashboard.left = this.dashboard.div.offsetLeft;
        this.dashboard.topMargin = this.dashboard.div.offsetTop;
        this.dashboard.leftMargin = this.dashboard.div.offsetLeft;
    }

    if (!this.dashboard.div) {
        this.dashboard.div = document.createElement("span");
        this.dashboard.width = 0;
        this.dashboard.height = 0;
        this.dashboard.top = 0;
        this.dashboard.left = 0;
    }
}



function VAddEvent(elm, evType, fn, useCapture) {
    if (elm.addEventListener) {
        elm.addEventListener(evType, fn, useCapture);
        return true;
    }
    else if (elm.attachEvent) {
        var r = elm.attachEvent('on' + evType, fn);
        return r;
    }
    else {
        elm['on' + evType] = fn;
    }
}

function VGetDirections(fromAddress, toAddress, callBack) {
    if (fromAddress.length > 0 && toAddress.length > 0) {
        var options = new VERouteOptions();

        options.RouteCallback = VDirectionsOnRoute;
        options.RouteCallback.map = this;
        this.directionsCallback = callBack;
        var color = SE_GetBackgroundColor('formHeader');
        // show an appropriate color but don't make it too light

        if (!isNaN(HexToR(color))) {
            var r = HexToR(color)
            var g = HexToG(color)
            var b = HexToB(color)

            if (r + g + b > 128 * 3) {
                scaleBy = (128 * 3) / (r + g + b);

                r = parseInt(r * scaleBy);
                g = parseInt(g * scaleBy);
                b = parseInt(b * scaleBy);
            }
            options.RouteColor = new VEColor(r, g, b, .7);
        }
        this.map.GetDirections([fromAddress, toAddress], options);
        this.clearMarkers();
    }
}

function VDirectionsOnRoute(route) {
    // Unroll route
    
    if (route) {
        
        var turns = "<div class=pd_map_driving_directions_steps>Total distance: " + route.Distance.toFixed(1) + " mi";
        var hours = Math.floor((route.Time % 86400) / 3600);
        var minutes = Math.floor(((route.Time % 86400) % 3600) / 60);
        turns += "<br/>Total time: " + (hours > 0 ? hours + " hour" + (hours > 1 ? "s " : " ") : "") 
            + minutes + " minutes " + "</div>";
        
        var legs = route.RouteLegs;
        var numTurns = 0;
        var leg = null;

        // Get intermediate legs
        for (var i = 0; i < legs.length; i++) {
            // Get this leg so we don't have to derefernce multiple times
            leg = legs[i];  // Leg is a VERouteLeg object

            // Unroll each intermediate leg
            var turn = null;  // The itinerary leg
            turns += '<ol class="pd_map_driving_directions_steps">';
            for (var j = 0; j < leg.Itinerary.Items.length; j++) {
                turn = leg.Itinerary.Items[j];  // turn is a VERouteItineraryItem object
                numTurns++;
                var hints = "";
                if (turn.Hints) {
                    for (var i = 0; i < turn.Hints.length; i++) {
                        hints += (hints != "" ? "<br/>" : "") + turn.Hints[i].Text;
                    }
                }
                turns += "<li>" + turn.Text + " (" + turn.Distance.toFixed(1) + " mi)"
                    + (hints != "" ? "<div class=\"pd_directions_hints\">" + hints + "</div>": "") + "</li>";
            }
            turns += "</ol>"; 
        }
    }
    else
        turns = "Sorry, be we couldn't find directions for the addresses you entered.";

    this.RouteCallback.map.directionsCallback(turns);
}


// drawing methods
function VInitDrawing() {
    if (this._drawShapeLayer)
        this.map.DeleteShapeLayer(this._drawShapeLayer);
    
    this._drawShapeLayer = new VEShapeLayer();    
    this.map.AddShapeLayer(this._drawShapeLayer);
    this._drawGeomType = null;
    this._drawCurrentShape = null;
    this._drawPoints = new Array();
    this._drawCurrentLatLong;
    this._tempShape = null;
    this._tempPoints = null;
    this._drawCirclePoints = null;
    this._tempCircle = null;
    this._tempDistance = 0;
    this._drawShapeIndex = 1;
    this._drawCurrentShapeID = "";
    this._drawProximityDeltaLatLong = null;
    this._drawProximityPixels = 5;
    this.drawIsDrawing = false;

    V_DrawSetCurrentMap.map = this;

    // methods
    this.drawPolyMouseClick = VDrawPolyMouseClick;
    this.drawPolyMouseMove = VDrawPolyMouseMove;
    this.drawDeleteShape = VDrawDeleteShape;
    this.drawGetCirclePoints = VDrawGetCirclePoints;
    this.drawIsCloseToStartOrEndPoint = VDrawIsCloseToStartOrEndPoint;
    this.drawLoadShape = VDrawLoadShape;
    this.drawResizeToFitSelection = VDrawResizeToFitSelection;
}

function VStartDraw(geomType, drawCallback) {

    this.drawInit();
    this._drawGeomType = geomType.toLowerCase();
    this.map.AttachEvent("onclick", V_DrawPolyMouseClick);
    V_DrawMouseMove.map = this;
    this.map.AttachEvent("onmousemove", V_DrawMouseMove);
    this.drawIsDrawing = true;
    VDrawSetCursor(this)
    this.drawCallback = drawCallback;
}

function VDrawSetCursor(seMap) {
    if (seMap.drawIsDrawing) {
        seMap._mapDiv.style.cursor = 'crosshair';
        setTimeout('VDrawSetCursor(' + seMap.id + ')', 200);
    }
}

function VDrawDone(isClear) {
    try {
        SEMap.ClosePopups()
        this.drawIsDrawing = false;
        this.map.DetachEvent("onmousemove", V_DrawPolyMouseMove);
        this.map.DetachEvent("onclick", V_DrawPolyMouseClick);
        this._drawShapeLayer.DeleteShape(this._tempShape);
        this._drawShapeLayer.DeleteShape(this._tempCircle);
    }
    catch (err) {

    }

    if (this._drawGeomType == "circle" && !(this._drawCirclePoints && this._drawCirclePoints.length > 3)) {
        this._drawCirclePoints = null;
        this._drawPoints = new Array();
        this.mapBoundaryPoints = new Array();
    }
    else if (this._drawPoints.length < 3) {
        this._drawPoints = new Array();
        this.mapBoundaryPoints = new Array();
    }
    else {
        if (!isClear) {
            this.drawLoadShape();
            this.drawResizeToFitSelection(this._drawPoints);
        }
    }
    this._mapDiv.style.cursor = "";
    this._tempPoints = null;
    this._tempDistance = 0;

    if (this.drawCallback)
        this.drawCallback();
    if (this.functionToCallOnZoom)
        this.functionToCallOnZoom(true);
}

function VDrawResizeToFitSelection(points) {
    var northWest = new SEPoint(-90, 180);
    var southEast = new SEPoint(90, -180);
    for (i = 0; i < points.length; i++) {
        if (points[i].Latitude < southEast.latitude)
            southEast.latitude = points[i].Latitude;
        if (points[i].Longitude > southEast.longitude)
            southEast.longitude = points[i].Longitude;
        if (points[i].Latitude > northWest.latitude)
            northWest.latitude = points[i].Latitude;
        if (points[i].Longitude < northWest.longitude)
            northWest.longitude = points[i].Longitude;

    }
    var bounds = new SEBounds(northWest, southEast);
    this.setBestMapView(bounds);
    this.isLoading = false;
    this.updateBounds();
}

function VDrawLoadBoundaryPoints() {
    this.drawInit();
    for (i = 0; i < this.mapBoundaryPoints.length; i++) {
        var sePoint = this.mapBoundaryPoints[i];
        this._drawPoints[i] = new VELatLong(sePoint.latitude, sePoint.longitude);
    }
    this._drawGeomType = VEShapeType.Polygon.toLowerCase();
    this.drawLoadShape();
}

function VDrawLoadShape() {
    this._drawCurrentShape = null;
    switch (this._drawGeomType) {
        case "polygon":
        case "rectangle":
            if (this._drawPoints.length > 2)
                this._drawCurrentShape = new VEShape(VEShapeType.Polygon, this._drawPoints);

            break;
        case "polyline":
            this._drawCurrentShape = new VEShape(VEShapeType.Polyline, this._drawPoints);
            break;
        case "circle":
            this._drawCurrentShape = new VEShape(VEShapeType.Polygon, this._drawCirclePoints);
            break;
        case "point":
            this._drawCurrentShape = new VEShape(VEShapeType.Pushpin, this._drawCurrentLatLong);
            break;
    }

    if (this._drawCurrentShape) {
        VSetShapeColor(this._drawCurrentShape);

        this._drawShapeLayer.AddShape(this._drawCurrentShape);
        var thisShape = this._drawCurrentShape;
        this._drawCurrentShapeID = "shape" + this._drawShapeIndex;
        this._drawShapeIndex++;
    }
}

function VSetShapeColor(shape) {
    shape.HideIcon();
    var lineColor = new VEColor(0, 0, 0, 1);
    var fillColor = new VEColor(128, 128, 128, .3);

    shape.SetLineColor(lineColor);
    shape.SetLineWidth(1);
    shape.SetFillColor(fillColor);
}

function VDrawGetPoints() {
    var sePoints = new Array();
    if (this._drawPoints) {
        for (var i = 0; i < this._drawPoints.length; i++) {
            sePoints[sePoints.length] = new SEPoint(this._drawPoints[i].Latitude, this._drawPoints[i].Longitude);
        }
    }
    return sePoints;
}
function VDrawGetPointsString() {
    var myPoints = this.drawGetPoints();
    var ret = "";
    for (i = 0; i < myPoints.length; i++) {
        ret += (ret != "" ? "|" : "") + myPoints[i].latitude + "," + myPoints[i].longitude;
    }
    return ret;
}

// ------- static draw methods ------------
function V_DrawSetCurrentMap(e) {

    var seMap = typeof(V_DrawSetCurrentMap.map) != 'undefined' ? V_DrawSetCurrentMap.map : SEMap_GetCurrentMap();
    var xy = VAdjustMapXYForBrowser(e);

    seMap._drawCurrentLatLong = seMap.map.PixelToLatLong(new VEPixel(xy.x, xy.y));

    if (!seMap._drawProximityDeltaLatLong) {
        var proximityLatLong = seMap.map.PixelToLatLong(
            new VEPixel(xy.x + seMap._drawProximityPixels, xy.y + seMap._drawProximityPixels));
        seMap._drawProximityDeltaLatLong = new VELatLong(
            Math.abs(proximityLatLong.Latitude) - Math.abs(seMap._drawCurrentLatLong.Latitude),
            Math.abs(proximityLatLong.Longitude) - Math.abs(seMap._drawCurrentLatLong.Longitude))
    }
    return seMap;
}

function V_DrawMouseMove(e) {
    var seMap = V_DrawSetCurrentMap(e);
}

function V_DrawPolyMouseClick(e) {
    var seMap = V_DrawSetCurrentMap(e);
    seMap.drawPolyMouseClick(e);
}

function V_DrawPolyMouseMove(e) {
    var seMap = V_DrawSetCurrentMap(e);
    seMap.drawPolyMouseMove();
}

function VDrawGetDistance(p1, p2, units) {
    var p1Lat = V_DrawLatLonToRadians(p1.Latitude);
    var p1Lon = V_DrawLatLonToRadians(p1.Longitude);

    var p2Lat = V_DrawLatLonToRadians(p2.Latitude);
    var p2Lon = V_DrawLatLonToRadians(p2.Longitude);

    if (!p1Lat) {
        p1Lat = V_DrawLatLonToRadians(p1.latitude);
        p1Lon = V_DrawLatLonToRadians(p1.longitude);

        p2Lat = V_DrawLatLonToRadians(p2.latitude);
        p2Lon = V_DrawLatLonToRadians(p2.longitude);
    }

    var R = 6371; // earth's mean radius in km
    var dLat = p2Lat - p1Lat;
    var dLong = p2Lon - p1Lon;
    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(p1Lat) * Math.cos(p2Lat) * Math.sin(dLong / 2) * Math.sin(dLong / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var disKm = R * c;
    //var disMiles = disKm * 0.6214;
    if (units && units == "miles")
        return (disKm * 0.6214);
    else
        return (disKm);
}

function V_DrawLatLonToRadians(point) {
    return point * Math.PI / 180;
}
// ------- end static draw methods ------------


function VDrawPolyMouseClick(e) {
    if (this._drawPoints.length == 0 && this._drawGeomType != "point") {
        this.map.DetachEvent("onmousemove", V_DrawMouseMove);
        this.map.AttachEvent("onmousemove", V_DrawPolyMouseMove);
        this._mapDiv.style.cursor = 'crosshair';
    }
    
    if (this._drawGeomType == "circle" && (this._tempPoints && this._tempPoints.length == 2)) {
        this._drawPoints[0] = this._tempPoints[0];
        this._drawPoints[1] = this._tempPoints[1];
        this.drawDone();
    }
    else if (this._drawGeomType == "rectangle" && (this._tempPoints && this._tempPoints.length == 2)) {
        this._drawPoints.length = 4
        this._drawPoints[0] = this._tempPoints[0];
        this._drawPoints[1] = new VELatLong(this._tempPoints[0].Latitude, this._tempPoints[1].Longitude);
        this._drawPoints[2] = this._tempPoints[1];
        this._drawPoints[3] = new VELatLong(this._tempPoints[1].Latitude, this._tempPoints[0].Longitude);
        this.drawDone();
    }
    else {
        if (this._drawPoints.length > 2 && this.drawIsCloseToStartOrEndPoint())
            this.drawDone();
        else
            this._drawPoints.push(this._drawCurrentLatLong);
    }

    if (e.rightMouseButton) {
        this.drawDone();
    }
    else {
        this._mapDiv.style.cursor = 'crosshair';
    }
}

function VDrawIsCloseToStartOrEndPoint() {
    if (this._drawPoints.length > 0) {
        var iLast = this._drawPoints.length - 1;
        if (Math.abs(Math.abs(this._drawCurrentLatLong.Latitude) - Math.abs(this._drawPoints[0].Latitude))
            < Math.abs(this._drawProximityDeltaLatLong.Latitude)) {
            if (Math.abs(Math.abs(this._drawCurrentLatLong.Longitude) - Math.abs(this._drawPoints[0].Longitude))
                < Math.abs(this._drawProximityDeltaLatLong.Longitude))
                return true;
        }
        else if (Math.abs(Math.abs(this._drawCurrentLatLong.Latitude) - Math.abs(this._drawPoints[iLast].Latitude))
            < Math.abs(this._drawProximityDeltaLatLong.Latitude)) {
            if (Math.abs(Math.abs(this._drawCurrentLatLong.Longitude) - Math.abs(this._drawPoints[iLast].Longitude))
                < Math.abs(this._drawProximityDeltaLatLong.Longitude)) {
                return true;
            }
        }
    }
    return false;
}


function VDrawPolyMouseMove() {
    this._tempPoints = this._drawPoints.slice(0, this._drawPoints.length);

    if (this._drawGeomType == "circle" && this._tempPoints.length <= 2) {
        this._tempPoints[1] = this._drawCurrentLatLong;
        this._tempDistance = VDrawGetDistance(this._tempPoints[0], this._tempPoints[1]);

    }
    else if (this._drawGeomType == "rectangle" && this._tempPoints.length == 2) {
        this._tempPoints[1] = this._drawCurrentLatLong;
    }
    else {
        if (!this.drawIsCloseToStartOrEndPoint())
            this._tempPoints.push(this._drawCurrentLatLong);
        else
            return;
    }

    try {
        if (this._tempShape != null)
            this._drawShapeLayer.DeleteShape(this._tempShape);
        if (this._tempCircle != null)
            this._drawShapeLayer.DeleteShape(this._tempCircle);
    }
    catch (err) {
        return;
    }

    if (this._tempPoints.length == 2) {
        if (this._drawGeomType == "polygon") {
            this._tempShape = new VEShape(VEShapeType.Polyline, this._tempPoints);
            VSetShapeColor(this._tempShape);
            this._drawShapeLayer.AddShape(this._tempShape);
        }
        else if (this._drawGeomType == "rectangle") {
            rectPoints = new Array();
            rectPoints[0] = this._tempPoints[0];
            rectPoints[1] = new VELatLong(this._tempPoints[0].Latitude, this._tempPoints[1].Longitude);
            rectPoints[2] = this._tempPoints[1];
            rectPoints[3] = new VELatLong(this._tempPoints[1].Latitude, this._tempPoints[0].Longitude);

            this._tempShape = new VEShape(VEShapeType.Polygon, rectPoints);
            VSetShapeColor(this._tempShape);
            this._drawShapeLayer.AddShape(this._tempShape);
        }
    }

    if (this._tempPoints.length > 2) {
        switch (this._drawGeomType) {
            case "polygon":
                this._tempShape = new VEShape(VEShapeType.Polygon, this._tempPoints);
                break;
            case "polyline":
                this._tempShape = new VEShape(VEShapeType.Polyline, this._tempPoints);
                break;
        }
        VSetShapeColor(this._tempShape);
        this._drawShapeLayer.AddShape(this._tempShape);
    }
}

//Draw Circle
function VDrawGetCirclePoints() {
    var R = 6371; // earth's mean radius in km
    var lat = (this._drawPoints[0].Latitude * Math.PI) / 180; //rad
    var lon = (this._drawPoints[0].Longitude * Math.PI) / 180; //rad
    var d = parseFloat(this._tempDistance) / R;  // d = angular distance covered on earth's surface
    this._drawCirclePoints = new Array();
    for (x = 0; x <= 360; x++) {
        var p2 = new VELatLong(0, 0);
        var brng = x * Math.PI / 180; //rad
        p2.Latitude = Math.asin(Math.sin(lat) * Math.cos(d) + Math.cos(lat) * Math.sin(d) * Math.cos(brng));
        p2.Longitude = ((lon + Math.atan2(Math.sin(brng) * Math.sin(d) * Math.cos(lat), Math.cos(d) - Math.sin(lat) * Math.sin(p2.Latitude))) * 180) / Math.PI;
        p2.Latitude = (p2.Latitude * 180) / Math.PI;
        this._drawCirclePoints.push(p2);
    }
    return this._drawCirclePoints;
}

function VDrawDeleteShape(shapeID) {
    var delShape = this._drawShapeLayer.GetShapeByID(shapeID);
    this._drawShapeLayer.DeleteShape(delShape);

}

// overlay methods
function VOverlayDraw(overlaySEPoints) {
    if (this._overlayShapeLayer) {
        this._overlayShapeLayer.DeleteAllShapes();
    }
    this._overlayShapeLayer = new VEShapeLayer();
    this.map.AddShapeLayer(this._overlayShapeLayer);
    this._overlayPoints = new Array();
    if (overlaySEPoints)
        this._overlayBoundaryPoints = overlaySEPoints;

    for (i = 0; i < this._overlayBoundaryPoints.length; i++) {
        var sePoint = this._overlayBoundaryPoints[i];
        this._overlayPoints[i] = new VELatLong(sePoint.latitude, sePoint.longitude);
    }

    this._overlayCurrentShape = null;
    if (this._overlayPoints.length > 2)
        this._overlayCurrentShape = new VEShape(VEShapeType.Polygon, this._overlayPoints);

    if (this._overlayCurrentShape) {
        VSetOverlayShapeColor(this._overlayCurrentShape, new VEColor(0, 0, 0, 1), new VEColor(128, 128, 255, .3), 1, true);
        this._overlayShapeLayer.AddShape(this._overlayCurrentShape);
        this._overlayCurrentShapeID = "shape" + this._overlayShapeIndex;
        this._overlayShapeIndex++;
    }
}

function VSetOverlayShapeColor(shape, lineColor, fillColor, lineWidth, hideIcon) {
    if (hideIcon)
        shape.HideIcon();
    shape.SetLineColor(lineColor);
    shape.SetLineWidth(lineWidth);
    shape.SetFillColor(fillColor);
}

//  ---- DragZoom Methods
function VInitDragZoom() {
    if (this._dragZoomShapeLayer)
        this._dragZoomShapeLayer.DeleteAllShapes();
    this._dragZoomShapeLayer = new VEShapeLayer();
    this.map.AddShapeLayer(this._dragZoomShapeLayer);
    this._dragZoomPoints = new Array();
    this._dragZoomCurrentLatLong;
    this._tempDragZoomPoints = new Array();
    this._isDragZooming = false;

    // methods
    this.dragZoomMouseClick = VDragZoomMouseClick;
    this.dragZoomMouseMove = VDragZoomMouseMove;
}

function VDragZoomStart(e) {
    this.dragZoomInit();
    this.map.AttachEvent("onclick", V_DragZoomMouseClick);
    this.map.AttachEvent("onmousemove", V_DragZoomMouseMove);
    this._isDragZooming = true;
    VDragZoomSetCursor(this)
    this.dragZoomMouseClick(e);
}

function V_DragZoomMouseClick(e) {
   VDragZoomGetMap().dragZoomMouseClick(e);
}

function VDragZoomGetMap() {
     return typeof(VDragZoomGetMap.map) != 'undefined' ? VDragZoomGetMap.map : SEMap_GetCurrentMap();
}

function VDragZoomMouseClick(e) {
    var seMap = VDragZoomGetMap();
    seMap._dragZoomCurrentLatLong = VDrawGetCurrentLatLong(seMap, e);

    if (this._tempDragZoomPoints.length == 0) {
        this._tempDragZoomPoints[0] = seMap._dragZoomCurrentLatLong;
        VDragZoomSetCursor(this);
        return;
    }
    this._tempDragZoomPoints[1] = seMap._dragZoomCurrentLatLong;
    this._dragZoomPoints.length = 4
    this._dragZoomPoints[0] = this._tempDragZoomPoints[0];
    this._dragZoomPoints[1] = new VELatLong(this._tempDragZoomPoints[0].Latitude, this._tempDragZoomPoints[1].Longitude);
    this._dragZoomPoints[2] = this._tempDragZoomPoints[1];
    this._dragZoomPoints[3] = new VELatLong(this._tempDragZoomPoints[1].Latitude, this._tempDragZoomPoints[0].Longitude);
    this.dragZoomDone();
}

function VDrawGetCurrentLatLong(seMap, e) {
    var xy = VAdjustMapXYForBrowser(e);
    return seMap.map.PixelToLatLong(new VEPixel(xy.x, xy.y));
}

function V_DragZoomMouseMove(e) {
    VDragZoomGetMap().dragZoomMouseMove(e);
}

function VDragZoomMouseMove(e) {
    var seMap = VDragZoomGetMap();
    seMap._dragZoomCurrentLatLong = VDrawGetCurrentLatLong(seMap, e);
    this._tempDragZoomPoints[1] = this._dragZoomCurrentLatLong;

    this._dragZoomShapeLayer.DeleteAllShapes();

    rectPoints = new Array();
    rectPoints[0] = this._tempDragZoomPoints[0];
    rectPoints[1] = new VELatLong(this._tempDragZoomPoints[0].Latitude, this._tempDragZoomPoints[1].Longitude);
    rectPoints[2] = this._tempDragZoomPoints[1];
    rectPoints[3] = new VELatLong(this._tempDragZoomPoints[1].Latitude, this._tempDragZoomPoints[0].Longitude);

    _tempDragZoomShape = new VEShape(VEShapeType.Polygon, rectPoints);
    VSetShapeColor(_tempDragZoomShape);
    this._dragZoomShapeLayer.AddShape(_tempDragZoomShape);

}

function VDragZoomSetCursor(seMap) {
    if (seMap._isDragZooming) {
        seMap._mapDiv.style.cursor = 'crosshair';
        setTimeout('VDragZoomSetCursor(' + seMap.id + ')', 200);
    }
}

function VDragZoomDone() {
    this._isDragZooming = false;
    this.map.DetachEvent("onmousemove", V_DragZoomMouseMove);
    this.map.DetachEvent("onclick", V_DragZoomMouseClick);
    this._dragZoomShapeLayer.DeleteAllShapes();
    this._mapDiv.style.cursor = "";
    this.drawResizeToFitSelection(this._dragZoomPoints);
    this._dragZoomPoints = null;
}

function VAdjustMapXYForBrowser(e) {
    var xy = new SE_XY(e.mapX, e.mapY);
    if (SE_UserAgent("msie")) {
        //xy.x += document.body.scrollLeft;
        //xy.y += document.body.scrollTop;
    }
    return xy;
}


