﻿/*
 options 
 containerId - id of the container
 centerLat - latitude for the center of the map
 centerLng - longitude for the center of the map
 zoom - start zoom for the map
 showControls - boolean to display a map with no overlay controls
*/
function WDCMap(containerId, centerLat, centerLng, zoom, controlType, showMapTypeControl){

    this.container = null;
    this.layer = null;   
    this.gmap = null;   
    this.wait = null;
    //initialize the control
    this.latitude = centerLat;
    this.longitude = centerLng;
    this.zoom = zoom;
    this.origlatitude = centerLat;
    this.origlongitude = centerLng;
    this.origzoom = zoom;
    this.houseIcon = null;
    this.cityIcon = null;
    this.currentInfoWindowMarker = null;  //the marker with the infowindow opened
    this.mapMoveCallback = null;
    this.mapDragEventListener = null;
    this.mapZoomEventListener = null;
    this.streetViewContainer = null;
    this.streetViewLayer = null;
    this.gStreetView = null;
    
    this.gMarkerMgr = null;
    this.markers = null;
    
    this.mapTypeControl = null;
    this.mapControls = null;
    this.mapControlType = controlType;
    this.showMapTypeConrol = showMapTypeControl;
    
    this.isStreetViewShown = false;
    this.init(containerId, centerLat, centerLng, zoom);
}

WDCMap.prototype.init = function (mapid, latitude, longitude, zoom) {
   if (GBrowserIsCompatible()) {  
        this.container = document.getElementById(mapid);
       
        this.layer = document.createElement("div");
        this.layer.style.position = "absolute";
        this.layer.style.width = this.container.offsetWidth + 'px';
        this.layer.style.height = this.container.offsetHeight + 'px'; 
        this.container.appendChild(this.layer);
 
        
        //create the wait div and assign styles
        this.wait = document.createElement("div");
        this.wait.className = "wait";
        this.wait.style.visibility = "hidden";
        this.wait.style.width = this.layer.offsetWidth + 'px';
        this.wait.style.height = this.layer.offsetHeight + 'px'; 
        var strMsg;
        strMsg = "<table border='0' cellpadding='0' cellspacing='0' align='center' height='100%'>";
        strMsg += "<tr valign='center'><td align='center'>";
        strMsg += "<div><img src='" + _appPath + "/images/loading.gif' />&nbsp;&nbsp;<b>Please Wait...</b></div></td></tr></table>";
        this.wait.innerHTML = strMsg;
        this.container.appendChild(this.wait);

        this.showWait();
        // Create our "house" marker icon
        this.houseIcon = new GIcon(G_DEFAULT_ICON);
        this.houseIcon.image = _appPath + "/images/map_house.gif";
        this.houseIcon.shadow = _appPath + "/images/map_house_shadow.png";
        this.houseIcon.iconSize = new GSize(32, 31);
        this.houseIcon.shadowSize = new GSize(47, 36);
        this.houseIcon.iconAnchor = new GPoint(6, 31);
        this.houseIcon.infoWindowAnchor = new GPoint(5, 1);

        // city icon
        this.cityIcon = new GIcon();
        this.cityIcon.image = _appPath + "/images/search/cityhouses.gif";
        this.cityIcon.iconSize = new GSize(26, 24);
        this.cityIcon.iconAnchor = new GPoint(13, 0);
        this.cityIcon.infoWindowAnchor = new GPoint(13, 0);

        this.gmap = new GMap2(this.layer);
        this.addMapControls();

        this.gmap.setCenter(new GLatLng(latitude, longitude), zoom);
        this.gMarkerMgr = new MarkerManager(this.gmap);       
        this.setMapType(getCookie("searchMapType"));
        
        var oThis = this;
        GEvent.addListener(this.gmap, "dragend", function() {
            if( oThis.gmap.getInfoWindow().isHidden()){
                oThis.SavePosition();
            }
        });
        GEvent.addListener(this.gmap, "zoomend", function(oldLevel,  newLevel) {
                oThis.SavePosition();
        });

        GEvent.addListener(this.gmap, "maptypechanged", function() {
                setCookie("searchMapType", oThis.gmap.getCurrentMapType().getUrlArg());
        });
        
        this.streetViewContainer = document.createElement("div");
        this.streetViewContainer.innerHTML = "<div style='background-color:white; color:black; border: solid 1px black; padding: 5px 5px 5px 5px; text-align: right;'><a href='javascript:void(0);' onclick='this.parentNode.parentNode.style.visibility=\"hidden\"; return false;'>Go back to map</a></div>"
        this.streetViewContainer.style.visibility = "hidden";
        this.streetViewContainer.style.position = "absolute";
        this.streetViewContainer.style.width = this.layer.offsetWidth + 'px';
        this.streetViewContainer.style.height = this.layer.offsetHeight + 'px'; 
        this.container.appendChild(this.streetViewContainer);

        this.streetViewLayer = document.createElement("div");
        this.streetViewLayer.className = "streetViewer";
        this.streetViewLayer.style.width = this.streetViewContainer.offsetWidth + 'px';
        this.streetViewLayer.style.height = (this.streetViewContainer.offsetHeight-27).toString() + 'px'; 
        this.streetViewContainer.appendChild(this.streetViewLayer);

        this.hideWait();
        
    }    
};

WDCMap.prototype.addMapControls = function(){
    if(this.showMapTypeConrol){
        if(this.mapTypeControl===null){this.mapTypeControl = new GMapTypeControl();}
    }
    
    switch(this.mapControlType){
        case "large":
            if(this.mapControls===null){this.mapControls = new GLargeMapControl();}
            break;
        case "large3d":
            if(this.mapControls===null){this.mapControls = new GLargeMapControl3D();}
            break;
        case "small":
            if(this.mapControls===null){this.mapControls = new GSmallZoomControl();}
            break;
        case "small3d":
            if(this.mapControls===null){this.mapControls = new GSmallZoomControl3D();}
            break;
        default:
            this.mapConrol = null;
    }
        
    if(this.mapTypeControl!=null){this.gmap.addControl(this.mapTypeControl);}
    if(this.mapControls!=null){this.gmap.addControl(this.mapControls);}
};

WDCMap.prototype.removeMapControls = function(){
    if(this.mapTypeControl!=null){this.gmap.removeControl(this.mapTypeControl);}
    if(this.mapControls!=null){this.gmap.removeControl(this.mapControls);}
};

WDCMap.prototype.openStreetView = function( markerInfo ) {
    var oThis = this;
    if( this.gStreetView === null ){
        this.gStreetView = new GStreetviewPanorama(this.streetViewLayer);
       GEvent.addListener(this.gStreetView, "error", function(errorCode) {
                if (errorCode == 603) {
                    oThis.hideStreetView();
                    alert("Error: Flash doesn't appear to be supported by your browser");
                    return;
                }
            });
    }
    var latlng = new GLatLng(markerInfo.lat, markerInfo.lng);
    
    if (markerInfo.panoData.code != 200) {alert('Street View unavailable at this location'); return;}
    this.streetViewContainer.style.visibility = "";
    var angle = computeAngle(latlng, markerInfo.panoData.location.latlng);
    this.gStreetView.setLocationAndPOV(markerInfo.panoData.location.latlng, {yaw: angle});
    this.isStreetViewShown = true;
}

WDCMap.prototype.hideStreetView = function() {
    this.streetViewContainer.style.visibility = "hidden";
    this.gStreetView.hide();
    this.isStreetViewShown = false;
}

WDCMap.prototype.setMapMoveCallback = function( callback ) {
    this.mapMoveCallback = callback;
    this.mapDragEventListener = GEvent.addListener(this.gmap, "dragend", callback);
    this.mapZoomEventListener = GEvent.addListener(this.gmap, "zoomend", callback);
}

WDCMap.prototype.removeMapMoveCallback = function() {
    if( this.mapDragEventListener !== null ){
        GEvent.removeListener(this.mapDragEventListener);    
        this.mapDragEventListener = null;
    }
    if( this.mapZoomEventListener !== null ){
        GEvent.removeListener(this.mapZoomEventListener);    
        this.mapZoomEventListener = null;
   }
   this.mapMoveCallback = null;
}

WDCMap.prototype.SavePosition = function () {
    this.gmap.savePosition();
};

WDCMap.prototype.setMapType = function (type) {
    var types = this.gmap.getMapTypes();
    for(var i = 0; i < types.length; i++){
        if(types[i].getUrlArg() == type){
            this.gmap.setMapType(types[i]);
            break;
        }
    }
};

WDCMap.prototype.getMapType = function () {
    this.gmap.getCurrentMapType().getUrlArg()
};

WDCMap.prototype.showWait = function() {
    this.wait.style.visibility = "visible";
};

WDCMap.prototype.hideWait = function() {
    this.wait.style.visibility = "hidden";
};

WDCMap.prototype.reset = function() {
    this.setLocation(this.origlatitude, this.origlongitude, this.origzoom);
    this.gmap.savePosition();
    if(this.mapMoveCallback!==null){
        var callback = this.mapMoveCallback;
        var t=setTimeout(callback,10);
    }
};

WDCMap.prototype.checkResize = function() {
    this.layer.style.width = this.container.offsetWidth + 'px';
    this.layer.style.height = this.container.offsetHeight + 'px'; 
    this.wait.style.width = this.layer.offsetWidth + 'px';
    this.wait.style.height = this.layer.offsetHeight + 'px'; 
    this.streetViewContainer.style.width = this.layer.offsetWidth + 'px';
    this.streetViewContainer.style.height = this.layer.offsetHeight + 'px'; 
    this.streetViewLayer.style.width = this.streetViewContainer.offsetWidth + 'px';
    this.streetViewLayer.style.height = (this.streetViewContainer.offsetHeight-27).toString() + 'px';
    
    var center = this.gmap.getCenter();
    this.gmap.checkResize();  
    if( this.gStreetView ){this.gStreetView.checkResize();}
    this.gmap.setCenter(center);  

};

WDCMap.prototype.setLocation = function(latitude, longitude, zoom) {
    if(this.isStreetViewShown){this.hideStreetView();}
    this.latitude = latitude;
    this.longitude = longitude;
    if( zoom <= 0 )
    {
        zoom = this.zoom;
    }
    else
    {
        this.zoom = zoom;
    }
    this.gmap.setCenter(new GLatLng(latitude, longitude), zoom);
};

WDCMap.prototype.setLocationFromText = function( location ) {
    if( location != "" )
    {
        var address = location;
        var geocoder = new GClientGeocoder();
        var oThis = this;
        if (geocoder) {
            this.showWait();
            geocoder.getLatLng(
                address,
                function(point) {
                   if (!point) {
                        alert("'" + address + "' is not a valid location.");
                    } else {
                        oThis.gmap.closeInfoWindow();
                        oThis.setLocation(point.lat(), point.lng(), 13)
                        if(oThis.mapMoveCallback){
                            oThis.mapMoveCallback();
                        }
                        
                    }
                    oThis.hideWait();
                }
            );
        }
    }
};

WDCMap.prototype.setMarker = function( lat, lng, html ) {

   // Set up our GMarkerOptions object
    var markerIcon = new GIcon(this.houseIcon);
    markerOptions = { icon:markerIcon };
    var point = new GLatLng(lat, lng);
    var marker = new GMarker(point, markerOptions);
    
    if( html ) {
        GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(html);
            });
    }
    this.gmap.addOverlay(marker);
};

WDCMap.prototype.createMarker = function( markerInfo ) {
    var point = new GLatLng(markerInfo.lat, markerInfo.lng);
    var marker;
    if(markerInfo.type && markerInfo.type == "house"){
        var markerIcon = new GIcon(this.houseIcon);
        if(markerInfo.index && markerInfo.index > 0 && markerInfo.index <= 10){
            markerIcon.image = _appPath + "/images/search/map_house" + markerInfo.index.toString() + ".gif";
            markerIcon.shadow = _appPath + "/images/search/map_house_shadow.png";
        }
        var markerOptions = { icon:markerIcon };
        marker = new GMarker(point, markerOptions);
    }
    else if(markerInfo.type && markerInfo.type == "city"){
        var markerIcon = new GIcon(this.cityIcon);
        var markerOptions = { icon:markerIcon };
        marker = new GMarker(point, markerOptions);
    }
    else{
        marker = new GMarker(point);
    }
        
    var oThis = this;
    //save panoData to marker info
    if(markerInfo.showSVLink===true){
        var panoClient = new GStreetviewClient();  
        panoClient.getNearestPanorama(point, function(panoData){
                markerInfo.panoData = panoData;
            });      
    }
    else{
        markerInfo.panoData=null;
    }

    //Setup maker events
    GEvent.addListener(marker, "infowindowclose", function() {
        oThis.currentInfoWindowMarker = null;
        oThis.gmap.returnToSavedPosition();
        oThis.addMapControls(); 
        });

    //open the infowindow only if it is not already opened.
    if(markerInfo.descId)
    {
        var descElement = document.getElementById(markerInfo.descId);
        if(descElement){
            var newElem = descElement.cloneNode(true);
            newElem.id = newElem.id + '_map';
            var temp = document.createElement("div");
            temp.appendChild(newElem);
            markerInfo.desc = temp.innerHTML;
        }
    }

    if(markerInfo.url) {
        GEvent.addListener(marker, "click", function() {
                window.location=markerInfo.url;
            });
    }
    else if( markerInfo.desc ) {
        GEvent.addListener(marker, "click", function() {
                oThis.showMarkerPopup(oThis, marker, markerInfo);
            });
            
        if( markerInfo.anchorId ) {
            var anchor =  document.getElementById(markerInfo.anchorId);
            if(anchor){
                anchor.onclick = function() {
                    oThis.showMarkerPopup(oThis, marker, markerInfo);
                    }
            }
        }
    }
    return marker;
};

WDCMap.prototype.showMarkerPopup = function( context, marker, markerInfo ) {
    if(context.isStreetViewShown){context.hideStreetView();}
    if( marker != context.currentInfoWindowMarker ){
        var popup = document.createElement("div");
        popup.innerHTML = markerInfo.desc;
        if(markerInfo.panoData){
            if(markerInfo.panoData.code == 200){
                //has streetview
                var svDiv = document.createElement("div");
                var link = document.createElement("a");
                link.href = "javascript:void(0);"
                link.innerHTML = "Street View";
                link.onclick = function(){
                        context.openStreetView(markerInfo);
                    }
                svDiv.appendChild(link);
                svDiv.style.clear='both';
                popup.appendChild(svDiv);
            }
        }
    
        marker.openInfoWindow(popup);
        context.removeMapControls(); 
        context.currentInfoWindowMarker = marker;
    }
}

WDCMap.prototype.clearMarkers = function() {
    this.gMarkerMgr.clearMarkers();
    this.gMarkerMgr.refresh();
}

WDCMap.prototype.addMarkers = function( markerInfoList, bestFit ) {
    var bounds = this.gmap.getBounds();
    this.markers = [];        
    for( var i in markerInfoList ) {
        var marker = this.createMarker(markerInfoList[i])
        this.markers.push( marker );

        if( bestFit == true ) { bounds.extend(marker.getLatLng()); }        
    }
    
    this.gMarkerMgr.addMarkers(this.markers,0);
    this.gMarkerMgr.refresh();

    if( bestFit == true ) {
        this.gmap.setZoom(this.gmap.getBoundsZoomLevel(bounds));  
        this.gmap.setCenter(bounds.getCenter());  
        this.gmap.savePosition();
        
        this.origlatitude = this.gmap.getCenter().lat();
        this.origlongitude = this.gmap.getCenter().lng();
        this.origzoom = this.gmap.getZoom();
    }
};

WDCMap.prototype.getBounds = function() {
    var bounds = this.gmap.getBounds();
    return bounds.getSouthWest().toUrlValue() + ',' + bounds.getNorthEast().toUrlValue()
}

WDCMap.prototype.getZoom = function() {
    return this.gmap.getZoom().toString();
}

WDCMap.prototype.getMapInfo = function() {
    var bounds = this.gmap.getBounds();
    var zoom = this.gmap.getZoom();
    var center = this.gmap.getCenter();
    var info = "sw=" + bounds.getSouthWest().toUrlValue();
    info = info + "&nw=" + bounds.getNorthEast().toUrlValue();
    info = info + "&c=" + center.toUrlValue();
    info = info + "&z=" + zoom;
    return info;
};

WDCMap.prototype.openMarkerWindow = function(index){
    if(index >= 0 && index < this.markers.length){
        GEvent.trigger(this.markers[index],  "click"); 
    }
};


////////////////////////////
//WDCGeocoder
////////////////////////////
function WDCGeocoder(location){
}

WDCGeocoder.prototype.getLatLng = function (location, callback) {
    var geocoder = new GClientGeocoder();
    if( geocoder ) {
        geocoder.getLatLng(
        location,
        callback
        );
    }
};

function WDCUnloadMaps(){
    GUnload();
}


function WDCStreetView(containerId){
    this.streetViewContainer = null;
    this.gStreetView = null;
    this.init(containerId);
}

WDCStreetView.prototype.init = function (containerId) {
    var oThis = this;
    this.streetViewContainer = document.getElementById(containerId);
    this.gStreetView = new GStreetviewPanorama(this.streetViewContainer);
    GEvent.addListener(this.gStreetView, "error", function(errorCode) {
            if (errorCode == 603) {
                alert("Error: Flash doesn't appear to be supported by your browser");
                return;
            }
        });
};

WDCStreetView.prototype.open = function( lat, lng, callback ) {
    var latlng = new GLatLng(lat, lng);
    var panoClient = new GStreetviewClient();  
    var oThis = this;
    panoClient.getNearestPanorama(latlng, function(panoData){
            if (panoData.code != 200) { 
                if(callback){
                    callback(false);
                } 
            }
            else {
                var angle = computeAngle(latlng, panoData.location.latlng);
                oThis.gStreetView.setLocationAndPOV(panoData.location.latlng, {yaw: angle});
                if(callback){
                    callback(true);
                }
           }
        });      
}



function CreateMap(mapId, mapData, lat, lng, zoom, location, onReadyCallback,controlType,showMapTypeControl,smartView){
    if(location!==null&&location!==""){
        var geocoder = new WDCGeocoder(); 
        geocoder.getLatLng(location, function(point) {
                                      var map;
                                      if (!point) { map = new WDCMap(mapId,lat,lng,zoom,controlType,showMapTypeControl);}
                                      else {map = new WDCMap(mapId,point.lat(),point.lng(),zoom,controlType,showMapTypeControl);}
                                      map.addMarkers(mapData,smartView);
                                      if(onReadyCallback){onReadyCallback(map);}} );
    }
    else{
        var map = new WDCMap(mapId,lat,lng,zoom,controlType,showMapTypeControl);
        map.addMarkers(mapData,smartView);
        if(onReadyCallback){onReadyCallback(map);}
    }
}


function computeAngle(endLatLng, startLatLng) {
  var DEGREE_PER_RADIAN = 57.2957795;
  var RADIAN_PER_DEGREE = 0.017453;

  var dlat = endLatLng.lat() - startLatLng.lat();
  var dlng = endLatLng.lng() - startLatLng.lng();
  // We multiply dlng with cos(endLat), since the two points are very closeby,
  // so we assume their cos values are approximately equal.
  var yaw = Math.atan2(dlng * Math.cos(endLatLng.lat() * RADIAN_PER_DEGREE), dlat)
         * DEGREE_PER_RADIAN;
  return wrapAngle(yaw);
}

function wrapAngle(angle) {
if (angle >= 360) {
  angle -= 360;
} else if (angle < 0) {
 angle += 360;
}
return angle;
}