﻿// RTIMap
//
// Parameters:
//  mapId                   - the id of the map
//  locatorMapId            - the id of the locator map
//  locatorMapContainerId   - the id of the locator map
//  mapType                 - 'MS' or 'google'
//  mapLat
//  mapLng
//  mapAlt
//  opacity
//  pixelWidth              - of the sensor polylines.
//  arBeacons               - array of beacon devices.
//  arCameras               - array of camera devices.
//  arRadios                - array of radio devices.
//  arSensors               - array of sensor devices.
//  arSigns                 - array of sign devices.
//  mouseoverHandler        - a function to handle the popup logic. Used by VE only.
//  centerMapHandler        - a function that handles events that need to center a map.
//  shapeEventHandler       - a function that handles the MS shape event's click event. Used by VE only.
//  sensorClickHandler      - a function to handle the sensor click events.
//  zoomEndHandler          - a function to handle the zoomend event.
//
// Modification Log:
//  2008-05-28 RMG: I added the public function, ReplacePinD, which can be used to replace a marker icon.
//  2008-05-29 RMG: Check the device's active flag. If not active, do not process it.
//		    Added iconWidth and iconHeight.
//  2008-07-22 RMG: I added a public property for the zoomend event handler. If not null, I attach it to the 
//                  Google Map zoomend event.
//
function RTIMap(mapId, locatorMapId, locatorMapContainerId, mapType, mapLat, mapLng, mapAlt, opacity, pixelWidth, arBeacons, arCameras, arRadios, arSensors, arSigns, mouseoverHandler, centerMapHandler, shapeEventHandler, sensorClickHandler, zoomEndHandler) {
    // Private Properties
    this.baseIcon = null;
    this.gEvt = null;
    this.gZoomEndEvt = null;
    this.gQColor = new Array();
    this.iconHeight = 18;		// Used by Google Maps API
    this.iconWidth = 16;		// Used by Google Maps API
    this.inMap = null;
    this.locatorMapId = locatorMapId;
    this.map = null;
    this.mapId = mapId;
    this.mapAlt = mapAlt;
    this.mapLat = mapLat;
    this.mapLng = mapLng;
    this.mapsplit = document.getElementById(locatorMapContainerId);
    this.mapType = mapType;
    this.mouseoverHandler = mouseoverHandler;
    this.opacity = opacity;
    this.pixelWidth = pixelWidth;
    this.QColor = new Array();
    this.centerMapHandler = centerMapHandler;
    this.shapeEventHandler = shapeEventHandler;
    this.sensorClickHandler = sensorClickHandler;
    this.zoomEndHandler = zoomEndHandler;
    // Public Properties
    this.ViewTitle = '';
    // Device Collections
    this.Beacons = arBeacons;
    this.Cameras = arCameras;
    this.Radios = arRadios;
    this.Sensors = arSensors;
    this.Signs = arSigns;
    // Methods
    this.AddDeviceLayers = RTIMap_AddDeviceLayers;
    this.AddPinD = RTIMap_AddPinD;
    this.AddSensorLine = RTIMap_AddSensorLine;
    this.CenterLocatorMap = RTIMap_CenterLocatorMap;
    this.ClearMap = RTIMap_ClearMap;
    this.DrawPoly = RTIMap_DrawPoly;
    this.GetMap = RTIMap_GetMap;
    this.GetPointList = RTIMap_GetPointList;   
    this.GetShapeByID = RTIMap_GetShapeByID;
    this.Home = RTIMap_Home;
    this.MapView = RTIMap_MapView;
    this.RedisplaySensorLines = RTIMap_RedisplaySensorLines;
    this.ReplacePinD = RTIMap_ReplacePinD;
    this.ShowPopup = RTIMap_ShowPopup;
    this.SwitchMaps = RTIMap_SwitchMaps;
    this.ToggleLocatorMap = RTIMap_ToggleLocatorMap;
}

function RTIMap_AddDeviceLayers() {

	if (this.Sensors.length > 0) {
		//draw sensor lines
		for(var i=1; i < this.Sensors.length; i++) {
			if ( this.Sensors[i].active ) 
			    this.AddSensorLine(i,this.Sensors[i]);
		}
	}
	if (this.Signs.length > 0) {
		//Add the sign icons
		for (i=1; i < this.Signs.length; i++) {
		    if ( this.Signs[i].active )
    			this.AddPinD(this.Signs[i]);
		}
	}
	if (this.Radios.length > 0) {
		//add the radios
		for (i=1; i < this.Radios.length; i++) {
			if ( this.Radios[i].active )
			    this.AddPinD(this.Radios[i]);
		}
	}
	if (this.Cameras.length > 0) {
		//add the cameras
		for (i=1; i < this.Cameras.length; i++) {
			if ( this.Cameras[i].active && this.Cameras[i].role == 0)
			    this.AddPinD(this.Cameras[i]);
		}
	}
	if (this.Beacons.length > 0) {
		//add the beacons
		for (i=1; i < this.Beacons.length; i++) {
			if ( this.Beacons[i].active )
			    this.AddPinD(this.Beacons[i]);
		}
	}
}

//Routine to draw detector lines
function RTIMap_AddSensorLine(SensorNum, device) {

    var color;
	var PolyID = 'D' + SensorNum;
	var Points = this.GetPointList(SensorNum);

	if (this.mapType == "MS") {
		color = this.QColor[device.level];
	}
	else {
		color = this.gQColor[device.level];
	}
    this.DrawPoly(PolyID,
                  Points,
        		  this.pixelWidth,
		          color,
		          device);
}

//Routine to create an icon with popup handler
function RTIMap_AddPinD(device) {

	if (this.mapType=="MS") {
		var pin = new VEPushpin(device.pinID, 
		                        new VELatLong(device.lat,device.lng), 
		                        device.icon, 
		                        device.label, 
		                        device.description
                        		);
		VEPushpin.ShowDetailOnMouseOver = false;
		VEPushpin.OnMouseOverCallback = this.mouseoverHandler;
		this.map.AddPushpin(pin);
	
	} else {
        //google map
        var point = new GLatLng(device.lat,
                                device.lng);
        var deviceIcon = new GIcon(this.baseIcon);
        deviceIcon.image = device.icon;
	if (device.iconWidth == 0 && device.iconHeight == 0)
	{
		if (this.iconWidth > 0 && this.iconHeight > 0)
			deviceIcon.iconSize = new GSize(this.iconWidth, this.iconHeight);
	}
	else
	{
		deviceIcon.iconSize = new GSize(device.iconWidth, device.iconHeight);
	}
        var markerOpts = {icon:deviceIcon};
        var pin = new GMarker(point, markerOpts);
        this.map.addOverlay(pin);
        device.pin = pin;
        device.pinEventHandler = GEvent.addListener(pin, "mouseover", function() {
            GDownloadUrl(device.link+'?t='+Math.random(), function(data, responseCode) {
                if ( !responseCode || responseCode != 200 || data == '' ) {
                    pin.openInfoWindow("Error retrieving " + device.link);
                } else {
                    pin.openInfoWindowHtml(data, {maxWidth:device.popwidth});
                }
               });
		});
	}//end else not MS
}//addPinD

function RTIMap_CenterLocatorMap() {

	if (this.mapType=="MS") {
		if (this.map != null && this.inmap != null) {
			var latlng=this.map.GetCenter();
			this.inmap.SetCenter(latlng);
		}
	} else {
		if (this.map != null && this.inmap != null) {
			var latlng=this.map.getCenter();
			this.inmap.setCenter(latlng);
		}
	}
}

//function to clear Event handlers and clear map memory	
function RTIMap_ClearMap() {

    if ( this.mapType == 'MS' ) {
        this.map.DeleteAllPolylines();
        this.map.DeleteAllShapes();
        this.map.DetachEvent('onendcontinuouspan', this.centerMapHandler)
        this.map.DetachEvent('onchangeview', this.centerMapHandler)
        if ( this.shapeEventHandler != null ) {
            this.map.DetachEvent("onmouseover", this.shapeEventHandler);
            this.map.Clear();
        }
    } else {
        if ( this.gEvt != null ) {
            GEvent.removeListener(this.gEvt);
            this.gEvt = null;
        }
        if ( this.gZoomEndEvt != null ) {
            GEvent.removeListener(this.gZoomEndEvt);
            this.gZoomEndEvt = null;
        }
        if (this.Sensors.length > 0) {
            //Remove Event Listeners
            for(var i=1; i < this.Sensors.length; i++) {
                device = this.Sensors[i];
                if ( device != null && device.pinEventHandler != null ) {
                    GEvent.removeListener(device.pinEventHandler);
                    device.pinEventHandler = null;
                }
                if ( device != null && device.sensorEventHandler != null ) {
                    GEvent.removeListener(device.sensorEventHandler);
                    device.sensorEventHandler = null;
                }
            }
        }
        if (this.Signs.length > 0) {
            //Remove Event Listeners
            for (i=1; i < this.Signs.length; i++) {
                device = this.Signs[i];
                if ( device != null && device.pinEventHandler != null ) {
                    GEvent.removeListener(device.pinEventHandler);
                    device.pinEventHandler = null;
                }
                if ( device != null && device.sensorEventHandler != null ) {
                    GEvent.removeListener(device.sensorEventHandler);
                    device.sensorEventHandler = null;
                }
            }
        }
        if (this.Radios.length > 0) {
            //Remove Event Listeners
            for (i=1; i < this.Radios.length; i++) {
                device = this.Radios[i];
                if ( device != null && device.pinEventHandler != null ) {
                    GEvent.removeListener(device.pinEventHandler);
                    device.pinEventHandler = null;
                }
                if ( device != null && device.sensorEventHandler != null ) {
                    GEvent.removeListener(device.sensorEventHandler);
                    device.sensorEventHandler = null;
                }
            }
        }
        if (this.Cameras.length > 0) {
            //Remove Event Listeners
            for (i=1; i < this.Cameras.length; i++) {
                device = this.Cameras[i];
                if ( device != null && device.pinEventHandler != null ) {
                    GEvent.removeListener(device.pinEventHandler);
                    device.pinEventHandler = null;
                }
                if ( device != null && device.sensorEventHandler != null ) {
                    GEvent.removeListener(device.sensorEventHandler);
                    device.sensorEventHandler = null;
                }
            }
        }
        if (this.Beacons.length > 0) {
            //Remove Event Listeners
            for (i=1; i < this.Beacons.length; i++) {
                device = this.Beacons[i];
                if ( device != null && device.pinEventHandler != null ) {
                    GEvent.removeListener(device.pinEventHandler);
                    device.pinEventHandler = null;
                }
                if ( device != null && device.sensorEventHandler != null ) {
                    GEvent.removeListener(device.sensorEventHandler);
                    device.sensorEventHandler = null;
                }
            }
        }
    }
}

//routine to draw a polygon
function RTIMap_DrawPoly(id,points,width,color,device) {

	if (this.mapType=="MS") {
	    //draw a shape of the polyline
        var shape = new VEShape(VEShapeType.Polyline, points);
        shape.HideIcon();
        shape.SetLineColor(color);
        shape.SetLineWidth(width);
		this.map.AddShape(shape);
		device.shapeID = shape.GetId();
	} else {
		//draw Google Polyline
		var poly = new GPolyline(points,
    							 color,
	    						 width,
		    					 opacity);
		this.map.addOverlay(poly);
		// The only browser that I'm sure supports the polyline click event is IE. Firefox doesn't work.
		if(navigator.appName == "Microsoft Internet Explorer") {
		    if ( this.sensorClickHandler != null ) {
		        // Store the poly object
		        device.poly = poly;
        		// Add an event listener for the click event.
                device.sensorEventHandler = GEvent.addListener(poly, 'click', this.sensorClickHandler);
            }
        }
	} //end else
}//end drawpoly

function RTIMap_GetMap() {

    try {
        if (this.mapType=="MS") {
            //do MapPoint
            this.map = new VEMap(this.mapId);
            this.map.LoadMap(new VELatLong(this.mapLat, this.mapLng), parseInt(this.mapAlt)+1,'r',false);
            this.inmap = new VEMap(this.locatorMapId);
            this.inmap.LoadMap(new VELatLong(mapLat,mapLng),5,'h',true);
            this.inmap.HideDashboard();
            this.map.AttachEvent('onendcontinuouspan', this.centerMapHandler);
            this.map.AttachEvent('onchangeview', this.centerMapHandler);
            // The only browser that I'm sure supports the polyline click event is IE. Firefox doesn't work.
            if ( this.shapeEventHandler != null ) {
                if(navigator.appName == "Microsoft Internet Explorer") {
                    this.map.AttachEvent("onclick", this.shapeEventHandler);
                    this.QColor[0] = new VEColor(150,150,150,this.opacity);
                    this.QColor[1] = new VEColor(0,255,0,this.opacity);
                    this.QColor[2] = new VEColor(255,255,0,this.opacity);
                    this.QColor[3] = new VEColor(255,0,0,this.opacity);
                }
            }
        } else {
            //do google map
            this.map = new GMap2(document.getElementById(this.mapId));
            this.map.addControl(new GSmallMapControl());
            this.map.setCenter(new GLatLng(parseFloat(this.mapLat), parseFloat(this.mapLng)), parseInt(this.mapAlt)+1);
            this.inmap = new GMap2(document.getElementById(this.locatorMapId));
            this.inmap.setCenter(new GLatLng(parseFloat(this.mapLat), parseFloat(this.mapLng)), 5);
            this.inmap.setMapType(G_HYBRID_MAP);
            this.gEvt = GEvent.addListener(this.map,'moveend',this.centerMapHandler);
            if (this.zoomEndHandler != null)
                this.gZoomEndEvt = GEvent.addListener(this.map, 'zoomend', this.zoomEndHandler);
            // Create a base icon for all of our markers that specifies the
            // shadow, icon dimensions, etc.
            this.baseIcon = new GIcon();
            this.baseIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
            this.baseIcon.iconSize = new GSize(16, 16);
            this.baseIcon.shadowSize = new GSize(16, 16);
            this.baseIcon.iconAnchor = new GPoint(6, 10);
            this.baseIcon.infoWindowAnchor = new GPoint(9, 2);
            this.baseIcon.infoShadowAnchor = new GPoint(18, 25);
            this.gQColor[0] = "#969696";
            this.gQColor[1] = "#00ff00";
            this.gQColor[2] = "#ffff00";
            this.gQColor[3] = "#ff0000";
        }
        return true;
    } catch(e) {
        return false;
    }
}
	
//routine that returns a list of points for a sensor
function RTIMap_GetPointList(SensorNum) {

	var points = new Array();
	for (var x=0; x < this.Sensors[SensorNum].pLat.length; x++) {
		if (this.mapType == "MS") {
			points[x] = new VELatLong(this.Sensors[SensorNum].pLat[x], this.Sensors[SensorNum].pLng[x]);
		}
		else {
			points[x] = new GLatLng(this.Sensors[SensorNum].pLat[x], this.Sensors[SensorNum].pLng[x]);
		}
	}
	return points;
}

function RTIMap_GetShapeByID(id) {

    if (this.mapType=='MS') 
        return this.map.GetShapeByID(id);
    
    return null;
}
			 
function RTIMap_Home() {

	if (this.mapType=="MS") {
		this.map.SetCenterAndZoom(new VELatLong(this.mapLat, this.mapLng), parseInt(this.mapAlt)+1);
	} else {
		this.map.setCenter(new GLatLng(parseFloat(this.mapLat), parseFloat(this.mapLng)), parseInt(this.mapAlt)+1);
	}
}

function RTIMap_MapView(view) {

    if ( view == 'road' ) {
    	this.ViewTitle = "Map (Road View)";
    	if (this.mapType=="MS") {
			this.map.SetMapStyle(VEMapStyle.Road);
		} 
		else {
			this.map.setMapType(G_NORMAL_MAP);
		}
	} else {
		this.ViewTitle = "Map (Aerial View)";
		if (this.mapType=="MS") {
			this.map.SetMapStyle(VEMapStyle.Hybrid);
		} 
    	else {
			this.map.setMapType(G_HYBRID_MAP);
		}
	}	
}

function RTIMap_RedisplaySensorLines() {

	//Redisplay the sensor lines
	if (this.mapType=="MS") {
		this.map.DeleteAllPolylines();
	}
    if (this.Sensors.length > 0) {
	    //Remove Event Listeners
	    for(var i=1; i < this.Sensors.length; i++) {
		    device = this.Sensors[i];
		    if ( this.mapType == "google" ) {
    	        if ( device != null && device.pinEventHandler != null ) {
	                GEvent.removeListener(device.pinEventHandler);
	                device.pinEventHandler = null;
	            }
		        if ( device != null && device.sensorEventHandler != null ) {
    	            GEvent.removeListener(device.sensorEventHandler);
	                device.sensorEventHandler = null;
	            }
	            if ( device.poly != null )
    		        this.map.removeOverlay(device.poly);
            }
		    if ( device.active )
        		this.AddSensorLine(i, device);
	    }
    }
}

//Routine to replace an icon with popup handler
function RTIMap_ReplacePinD(device) {

	if (this.mapType=="MS") {
	    this.map.DeletePushpin(device.pinID);
	} else {
	    if ( device != null && device.pinEventHandler != null ) {
	        GEvent.removeListener(device.pinEventHandler);
	        device.pinEventHandler = null;
	    }
	    if ( device != null && device.sensorEventHandler != null ) {
	        GEvent.removeListener(device.sensorEventHandler);
	        device.sensorEventHandler = null;
	    }
	    if ( device.pin != null ) 
	        this.map.removeOverlay(device.pin);

	}//end else not MS
    if(device.active)
        this.AddPinD(device);
}//replacePinD

function RTIMap_ShowPopup(fIsError, point, text, width) {

    if ( this.mapType == 'google' ) {
        if ( !fIsError )
            this.map.openInfoWindowHtml(point, text, {maxWidth:width});
        else
            this.map.openInfoWindow(point, text);
    }
}

//function to switch between mapoint and google
function RTIMap_SwitchMaps(mtype) {

    this.ClearMap();

	this.map = null;
	this.inmap = null;
	this.mapType = mtype;

	if (this.GetMap()) {
		this.AddDeviceLayers();
    	this.ViewTitle = "Map (Road View)";
		return true;
	}
	else {
		return false;
	}
}

function RTIMap_ToggleLocatorMap() {

    if ( this.mapsplit != null ) {

        var mapsplitStyle = (document.layers) ? this.mapsplit : this.mapsplit.style;
        
    	if (mapsplitStyle.visibility == 'hidden') {
	    	mapsplitStyle.visibility = 'visible';
			this.CenterLocatorMap();
    	}
	    else {
		    mapsplitStyle.visibility = 'hidden';
		}
	}
}