// =============================================================================
// (c) 2008 MapJack.com
// Author: Bjorn Moren. bjorn@mapjack.com
// =============================================================================

//google.load("maps", "2");

//var _map = null;                     // Satellite map (google.maps.Map2)
var _dotOverlay = null;              // Dots overlay (google.maps.TileLayerOverlay)
var _dotOverlayVisible = true;
var _dotLayer = null
var _avatar = null;                  // Current position (google.maps.Marker)
var _beam = null;
var _beamDrag = null;
var _avatarImages = new Array();     // GIF images that makes up the avatar
//var _mapServer = "http://cpgimg.com/pano-tmp/dots/";
//var _localMapServer = "http://cpgimg.com/pano-tmp/dots/";
var _imageServer = "http://cpgimg.com/images/pano/";
var _avatarLat = 0;
var _avatarLon = 0;
var _avatarHeading = 0;
var _beamAngle = 90;
var _markers = new Array();

var _beamLength = 30;
var _canDragMap = true;
var _isDraggingBeam = false;
var _beamDragDist = 10;

var _dotOpacityForSat = [7,7,7,7,7,7,7,5,5,5,6,6,6,6,6,8,10,10,10,10];      // Dot opacity for the zoom levels, 0 - 10
var _dotOpacityForMap = [4,4,4,4,4,4,6,6,6,6,6,6,6,7,7,7,8,8,8,8];

var _mapEncodeChars = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789";

var crossIcon = "<div style='{position:relative;top:-20px;left:10px}' ><img src='/images/mapicon/shadow.png'></div>";
var beamImg = "<div class='avatarbeam'><img src='" + _imageServer + "BeamDrag.gif"  + "' /></div>";
var prevAvatarIcon;
var crossShape;
var currentShape;
var previousLoc = null;
var northBound = null;
var southBound = null;
var eastBound = null;
var westBound = null;

function createAvatar(lat, lng, idx) {
    var avatarIcon = "<div class='avatar' ><img src='" + _avatarImages[idx].src  +"' /></div>";

	_avatar = MapLIB.addPushpin({pinHTML: avatarIcon,
							pinIMG: _avatarImages[idx].src,
							lat:lat,
							lng:lng,
		 					viewPoint: '',
							zIndex:2000,
		 					id:"AVATAR"});
}

function removeAvatar() {
	if(_avatar) {
		MapLIB.getMapInstance().DeleteShape(_avatar);
		_avatar = null;
	}
}

function createBeamDrag(lat, lng) {
	_beamDrag = MapLIB.addPushpin({pinHTML: beamImg,
							pinIMG: _imageServer + "BeamDrag.gif",
		 					viewPoint: '',
		 					id:"AVATAR_BEAM"});
/*	
    _beamDrag = new GMarker(new GLatLng(lat, lng), {icon:beamIcon, draggable:true, bouncy:false, dragCrossMove:false});
    GEvent.addListener(_beamDrag, 'dragstart', beamDragStartHandler);
    GEvent.addListener(_beamDrag, 'drag', beamDragHandler);
    GEvent.addListener(_beamDrag, 'dragend', beamDragEndHandler);
    map.addOverlay(_beamDrag);
*/ 
}

function switchInit(initLat, initLng, code) {
	createAvatar(initLat, initLng, 0);
	//createBeamDrag(initLat, initLng);
	zoomEndHandler();

   	if(code && code != "")
   		navigateToEncoded(code);
   	else
   		navigateTo(initLat, initLng);
}

function initAvatarIcons() {
	_startPos = mapDecodePosition("rZEsXa8NYFMD"); // don't remove it

    for (var i = 0; i < 8; i++) {
        var image = new Image();
        image.src = _imageServer + "Avatar" + i + ".gif";
        _avatarImages[_avatarImages.length] = image;
    }
}

function removePanOverlays() {
	removeAvatar();
	/*
	if(_beamDrag) {
		map.DeleteShape(_beamDrag);
		_beamDrag = null;
	}
	*/
	if(_beam) {
		map.DeleteShape(_beam);
		_beam = null;
	}
	_avatarImages = [];
	/*
	if(_dotOverlay) {
		map.removeOverlay(_dotOverlay);
		_dotOverlay = null;
	}
	*/
}
/* ************************************************************************ */

function beamDragStartHandler() {
    _isDraggingBeam = true;
}

function beamDragEndHandler() {
	try {
		_beamDrag.Hide();
	} catch(e) {}

    _isDraggingBeam = false;
}

function beamDragHandler() {
    //var beamPos = _map.fromLatLngToDivPixel(_beamDrag.getPoint());
    //var beamPos = _map.fromLatLngToDivPixel(_mousePos);
    //var avatarPos = _map.fromLatLngToDivPixel(_avatar.getPoint());
    //var dragAng = 180 * Math.atan2(beamPos.x - avatarPos.x, avatarPos.y - beamPos.y) / Math.PI;
    //if (dragAng < 0) dragAng = 360 + dragAng;

    var beamPos = _beamDrag.GetPoints();
    var avatarPos = _avatar.GetPoints();
    var dragAng = 180 + 180 * Math.atan2(avatarPos[0].Longitude - beamPos[0].Longitude, avatarPos[0].Latitude - beamPos[0].Latitude) / Math.PI;

    _avatarHeading = dragAng;
    updateBeam();
    updateAvatar();

    turnTo(_avatarHeading);
}

function initModeHandler() {
}

function endPanHandler(e) {
	if(!mjStreetView.isStreetView)
		MapLIB.streetSceneButton();
}

function mouseDownHandler(e) {
	// if infobox is open, close it
	MapLIB.removeInfoBox();
	
	mjStreetView.downX = e.mapX;
	mjStreetView.downY = e.mapY;

	currentShape = map.GetShapeByID(e.elementID);

	if(e.elementID && currentShape._can_id == 'AVATAR') {
		avatarDragStartHandler();
		//crossShape = new VEShape(VEShapeType.Pushpin, map.PixelToLatLong(new VEPixel(e.mapX, e.mapY)));
		//crossShape.SetCustomIcon(crossIcon);
		//map.AddShape(crossShape);

		if(currentShape.GetType() == VEShapeType.Pushpin) {
		    mjStreetView.isAvatarMoving = true;
			preAvatarIcon = currentShape.GetCustomIcon().CustomHTML;
			var movingHTML = preAvatarIcon.replace('avatar', 'movingavatar');
		    currentShape.SetCustomIcon(movingHTML);
		    currentShape.SetPoints(map.PixelToLatLong(new VEPixel(e.mapX, e.mapY)));
		    map.vemapcontrol.EnableGeoCommunity(true);
		} 
		else {
		    currentShape = null;
		}
	} 
	else if(e.elementID && currentShape._can_id == 'AVATAR_BEAM') {
		MapLIB.vars.isClickedAvatarBeam = true;
	}

	MapLIB.vars.isMouseDown = true;
    MapLIB.vars.isCustomStartPan = false;
}

function mouseUpHandler(e) {
	if(mjStreetView.isAvatarMoving) {
		avatarDragEndHandler();

		mjStreetView.isAvatarMoving = false;
		currentShape.SetCustomIcon(preAvatarIcon);
		currentShape = null;
		map.vemapcontrol.EnableGeoCommunity(false);
	}

	// the same as endpan event
	if(MapLIB.vars.isMouseDown && MapLIB.vars.isCustomStartPan &&
	   !(mjStreetView.downX == e.mapX && mjStreetView.downY == e.mapY)) {
		if(mjStreetView.options.pageType == 'M') {
			if(iMap.isRefreshMapOn) {
				iMap.doIMapQuery(1);
			}
			else if(!mjStreetView.isStreetView)
				Webcam.getWebcamMarkers();
		} 
		else if(mjStreetView.options.pageType == 'PS' || mjStreetView.options.pageType == 'RL') {
			return false;// nothing
		}
		else {
			if(!mjStreetView.isStreetView)
				Webcam.getWebcamMarkers();
		}

		setPanBounds();
	    //beamDragEndHandler();
	}
	
	// they should be reset here not inside of above block
	MapLIB.vars.isMouseDown = false;
    MapLIB.vars.isClickedAvatarBeam = false;
}

function mouseMoveHandler(e) {
	// sometimes unhightbox doesn't work even with mouseout event so it remove hightlighted icon on mousemove event
	if(e.elementID == null && hShape != null) {
		unhighlightBox(highlightIndex);
	}
	
	// it plays role as a startpan event
    if(MapLIB.vars.isMouseDown && !MapLIB.vars.isCustomStartPan) {
    	if(!mjStreetView.autoPan && !mjStreetView.isStreetView) {
			mjStreetView.isTileDownloaded = false;
			//beamDragStartHandler();
		} 
        MapLIB.vars.isCustomStartPan = true; // only once per pan.
    }
    
	if(!_avatar) {
		return;
	}

    //if(MapLIB.vars.isMouseDown && MapLIB.vars.isClickedAvatarBeam) {
    //	beamDragHandler();
    //}
/*
    var avatarPos = _avatar.GetPoints();
    var pos = map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));
    _canDragMap = (MapLIB.veGetDistance(avatarPos, pos, false) > _beamDragDist);
    if(!_canDragMap) {
    	_beamDrag.Show();
        _beamDrag.SetPoints(pos);
    }
    else {
        _beamDrag.Hide();
    }    
*/
	var loc = map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));
    var latVariance = 0;
    var longVariance = 0;
    var panAmount = 10;
    var movingDirection = '';

    if(mjStreetView.isAvatarMoving) {
        currentShape.SetPoints(loc);

        //determine direction
        if(previousLoc){
            latVariance = loc.Latitude - previousLoc.Latitude
            longVariance = loc.Longitude - previousLoc.Longitude

            if(latVariance > 0)
                movingDirection = 'north';
            else if(latVariance < 0)
            	movingDirection = 'south';

            if(longVariance > 0)
                movingDirection = 'east';
            else if(longVariance < 0)
                movingDirection = 'west';
        }

        //pan map
        if((loc.Latitude < southBound) && movingDirection == 'south') {
        	mjStreetView.autoPan = true;
        	map.Pan(0, panAmount);
        }
        if((loc.Latitude > northBound) && movingDirection == 'north') {
        	mjStreetView.autoPan = true;
        	map.Pan(0, panAmount * -1);
        }
        if((loc.Longitude < westBound) && movingDirection == 'west') {
        	mjStreetView.autoPan = true;
        	map.Pan(panAmount * -1, 0);
        }
        if((loc.Longitude > eastBound) && movingDirection == 'east') {
        	mjStreetView.autoPan = true;
        	map.Pan(panAmount, 0);
        }

        previousLoc = loc;
    }
}

function mouseOutHandler(e) {
	if(e.elementID != null) {
		var shape = map.GetShapeByID(e.elementID);

		// highlighted pin
		if(shape._can_type == 'H-PIN') {
			unhighlightBox(highlightIndex);
			clearTimeout(t);
		}
	}
}

function mouseOverHandler(e) {
	if(e.elementID != null) {
		var shape = map.GetShapeByID(e.elementID);

		// mouse might keep hovering until users move out mouse 
		if(hShape != null && hShape.GetID() == shape.GetID()) {
			return true;
		}
		else if(shape._can_type != 'PIN') {
			return true;
		}
		else {
			var pinIdx = shape._can_id;
			var letter = MapLIB.getPinLetter(pinIdx);
			
			var pinHTML = MapLIB.getPinHTML(letter, true);
			var pinIMG = MapLIB.getPinIMG(letter, true);					

			var ll = shape.GetPoints();

			try { 
				if(highlightIndex > 0) 
					unhighlightBox(highlightIndex);
			} 
			catch(e) {}

			hShape = MapLIB.addPushpin({
				lat: ll[0].Latitude,
				lng: ll[0].Longitude,
				beakOffsetX:shape._can_beakOffsetX,
				beakOffsetY:shape._can_beakOffsetY,				
				pinHTML: pinHTML,
			 	pinIMG: pinIMG,
			 	id: pinIdx,
			 	type:"H-PIN",
			 	viewPoint:shape._can_viewPoint,
			 	title: shape.GetTitle(),
			 	desc: shape.GetDescription()});
			
			//highlightIndex = pinIdx;
			showListingBox(pinIdx);
			highlightBox(pinIdx);
		}
		
		return true;  
	}
}

// Handles user clicks on the map
function mouseClickHandler(e) {
	var map = MapLIB.getMapInstance();

	// as map is moved by dragging map, click event is fired.
	// So in order to identify click and dragging, keep point as of mousedown event.
	if(mjStreetView.downX == e.mapX && mjStreetView.downY == e.mapY) {
		if(e.elementID != null) { 
			var shape = map.GetShapeByID(e.elementID);
			// show infobox for orange pins and webcams
			if(!mjStreetView.isStreetView && (shape._can_type == 'H-PIN' || shape._can_type.indexOf('WEBCAMS') >= 0)) {
				if(!e.leftMouseButton) {
					/*
					if(shape._can_type == 'WEBCAMS-M') {
						document.getElementById('baseCSS').href = '/css/style_traffic.css';
						map.ShowInfoBox(shape);
					} else {
						document.getElementById('baseCSS').href = '/css/style.css';
						map.ShowInfoBox(shape);
					}
					*/
				} else {
					MapLIB.showInfoBox(shape, e);
				}
			}

			// don't move over traffic or web cameras
			if(shape._can_type.indexOf('WEBCAMS') >= 0) {
				return true;
			}
			
		    if(mjStreetView.isStreetView && e.leftMouseButton) {
		    	if(shape && shape._can_viewPoint)
		    		navigateToEncoded(shape._can_viewPoint);
		    	else if(shape) {
		    		var points = shape.GetPoints();
		    		mapNavigateTo(points[0].Latitude, points[0].Longitude);
		    	}
		    	else {
		        	var ll = map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));
		        	mapNavigateTo(ll.Latitude, ll.Longitude);
		    	}
		  	}
		}
		// for now, there is no 'Street Scene' for 'People Search', 'Reverse Lookup' and 'Traffic & Directions'. May 28, 2009
		else if(mjStreetView.options.pageType == 'PS' || mjStreetView.options.pageType == 'RL') {
			return true;
		}
		else if(mjStreetView.isStreetView) {
	    	var ll = map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));
	    	mapNavigateTo(ll.Latitude, ll.Longitude);
		}
	}
}

// in IE, doublclick triggers mousemove event which must be bug.
function doubleClickHandler(e) {
	if(map.GetZoomLevel() == 19) {	// maixmum
		return true;
	}
	else {
		// there is a little time delay to remove beak completely 
		setTimeout(function(){MapLIB.removeInfoBox();}, 300);
	}
}

// Handles mouse drags of avatar
// If Birds eye view style is selected, this is called 
function zoomEndHandler(e) {
	MapLIB.removeInfoBox();

	for(var i = 19; i >= 1; i--) {
		if(i == map.GetZoomLevel())
			jQuery('#zoomScale' + i).get(0).src = "/images/zoomstep_on.gif";
		else
			jQuery('#zoomScale' + i).get(0).src = "/images/zoomstep_off.gif";
	}	
	
	if(mjStreetView.options.pageType == 'PS' || mjStreetView.options.pageType == 'RL')
		return false;

	//if(mjStreetView.options.pageType == 'M' && iMap.isRefreshMapOn && !iMap.isInitZoomChanged && !iMap.isZoomIgnored && !mjStreetView.toggling) {
	if(mjStreetView.options.pageType == 'M' && iMap.isRefreshMapOn && !iMap.isZoomIgnored && !mjStreetView.toggling)
		iMap.doIMapQuery(1);
	else if(!mjStreetView.isStreetView)
		Webcam.getWebcamMarkers();

	if(mjStreetView.isStreetView) {
  	  /*
	  if(!_avatar) {
		  var lat = _avatarLat || _startPos.lat;
		  var lng = _avatarLat || _startPos.lon;
		  createAvatar(lat, lng, 0);
		  createBeamDrag(lat, lng);
	  }
	  */

	  var avatarPos = _avatar.GetPoints();
	  var pixPos = map.LatLongToPixel(avatarPos[0]);
	  var offsetPos = map.PixelToLatLong(new VEPixel(pixPos.x + _beamLength, pixPos.y));
	  _beamDragDist = MapLIB.veGetDistance(avatarPos, offsetPos, false);

	  updateBeam();
	}
	else {
		MapLIB.streetSceneButton();
	}
	
	if(mjStreetView.toggling)
		mjStreetView.toggling = false;
	
	//if(mjStreetView.options.pageType == 'M' && iMap.isInitZoomChanged)
	//	iMap.isInitZoomChanged = false;
	if(typeof iMap !== 'undefined' && iMap.isZoomIgnored)
		iMap.isZoomIgnored = false;
}

function setPanBounds() {
    var view = map.GetMapView();
    var topLeft = map.LatLongToPixel(view.TopLeftLatLong);
    var bottomRight = map.LatLongToPixel(view.BottomRightLatLong);
    
    var NBound = topLeft.x + 30;
    var SBound = bottomRight.x - 30;
    var EBound = bottomRight.y - 30;
    var WBound = topLeft.y + 30;
    
    var topLeftBound = map.PixelToLatLong(new VEPixel(NBound, WBound));
    var bottomRightBound = map.PixelToLatLong(new VEPixel(SBound, EBound));
    
    northBound = topLeftBound.Latitude;
    southBound = bottomRightBound.Latitude;
    westBound = topLeftBound.Longitude;
    eastBound = bottomRightBound.Longitude;
}

function showDots(show) {
    if (!_dotOverlay)
    	return false;

    if(show)
    	_dotOverlay.show(); 
    else 
    	_dotOverlay.hide();

    return true;
}

function updateMap(lat, lon, heading, viewAngle) {
    if (_isDraggingBeam) 
    	return false;

    /*
    if(!_avatar) {
		createAvatar(lat, lon, 0);
		createBeamDrag(lat, lon);
	}
	*/

    _avatarLat = lat;
    _avatarLon = lon;
    _avatarHeading = heading;
    _beamAngle = viewAngle;

    updateAvatar();
    updateBeam();

    return true;
}

// Called by the panorama when position or heading has changed
function updateAvatar() {
	//alert('updateAvatar - ' + _avatarLat + ':' +  _avatarLon);
    if (!_avatar) 
    	return;

    MapLIB.updatePushpin({
    		shape: _avatar,
    		lat: _avatarLat,
    		lng: _avatarLon,
    		pinHTML: "<div class='avatar'><img src='" + _avatarImages[Math.round(_avatarHeading / 45) % 8].src  + "'></div>", 
    		pinIMG: _avatarImages[Math.round(_avatarHeading / 45) % 8].src});
    
    /*
    MapLIB.updatePushpin({
		shape: _beamDrag,
		lat: _avatarLat,
		lng: _avatarLon,
		pinHTML: beamImg, 
		pinIMG: _imageServer + "BeamDrag.gif"});
	*/
    
    panVisible(_avatarLat, _avatarLon);
    setPanBounds();
    
    /*
    if (!_avatar) 
    	return;
    	
    var point = new GLatLng(_avatarLat, _avatarLon);
    _avatar.setPoint(point);
    map.savePosition(point);
    _avatar.setImage(_avatarImages[Math.round(_avatarHeading / 45) % 8].src);
    panVisible(_avatar);
    */  
}

//Makes sure a position is visible on the map
function panVisible(lat, lon) {
	var view = MapLIB.getMapInstance().GetMapView();
	
	var latDelta = (view.TopLeftLatLong.Latitude - view.BottomRightLatLong.Latitude) / 4;
	var lngDelta = (view.BottomRightLatLong.Longitude - view.TopLeftLatLong.Longitude) / 6;
	
	if (lat < view.BottomRightLatLong.Latitude + latDelta || lat > view.TopLeftLatLong.Latitude - latDelta ||
	     lon < view.TopLeftLatLong.Longitude + lngDelta || lon > view.BottomRightLatLong.Longitude - lngDelta) {
		MapLIB.getMapInstance().SetCenter(new VELatLong(lat, lon));
	}
 
 /*
 var bounds = map.getBounds();
 var size = bounds.toSpan();
 var sw = bounds.getSouthWest();
 var ne = bounds.getNorthEast();
 sw = new GLatLng(sw.lat() + size.lat()/10, sw.lng() + size.lng()/10);
 ne = new GLatLng(ne.lat() - size.lat()/10, ne.lng() - size.lng()/5);
 bounds = new GLatLngBounds(sw, ne);
 if (!bounds.contains(pos.getPoint()))
     map.panTo(pos.getPoint());
  */    
}

function updateBeam() {
    if (!_avatar || (_avatarLat == 0 && _avatarLon == 0)) {
    	return;
    }

    if (_beam) 
    	map.DeleteShape(_beam);
    
    _beam = null;
    
    /*if (map.getZoom() <= 12) 
    	return;  */
    var roundNess = parseInt(_beamAngle / 10);
    if (roundNess < 2) 
    	roundNess = 2;

    var avatarPoint = (_avatar.GetPoints())[0];
    var center = map.LatLongToPixel(avatarPoint);//map.fromLatLngToDivPixel(_avatar.getPoint());
    var beamAngle = _beamAngle * Math.PI / 180;
    var heading = _avatarHeading * Math.PI / 180;
    var points = [] ;// new Array();
    points.push(avatarPoint);
    for (var i = 0; i <= roundNess; i++)  {
        var ang = heading + (beamAngle * i / roundNess) - (beamAngle / 2);
        var x = Math.sin(ang) * _beamLength;
        var y = -Math.cos(ang) * _beamLength;
        var p = map.PixelToLatLong(new VEPixel(x + center.x, y + center.y)); //map.fromDivPixelToLatLng(new GPoint(x + center.x, y + center.y));
        points.push(p);
    }
    points.push(avatarPoint);

    _beam = MapLIB.addPolygon({
    	points:points,
    	lineColor:{opacity:1,R:102,G:102,B:255},
    	fileColor:{opacity:0.1,R:170,G:170,B:170},
    	lineWidth:1
    });
}

// Calls the panorama application to move to a coordinate
function mapNavigateTo(lat, lon) {
    navigateTo(lat, lon, true);
}

// Handles mouse drags of avatar
function avatarDragStartHandler() {
    if (_beam) 
    	map.DeleteShape(_beam);
    
    _beam = null;
}

// Handles mouse drags of avatar
function avatarDragEndHandler() {
    var point = _avatar.GetPoints();
    mapNavigateTo(point[0].Latitude, point[0].Longitude);
}

/*
function zoomPanOnMarkers()
{
    if (!map) return false;
    var bounds = new GLatLngBounds();
    for (var i = 0; i < _markers.length; i++) bounds.extend(_markers[i].getPoint());
    var zoom = map.getBoundsZoomLevel(bounds);
    if (zoom > 16) zoom = 16; 
    map.setZoom(zoom);
    map.setCenter(bounds.getCenter());
    return true;
}

function removeMarkers()
{
    if (!map) return false;
    while (_markers.length > 0) map.removeOverlay(_markers.pop());
    return true;
}
*/

function mapDecodePosition(code) {
  if (code == null || code.length < 10) return null;
	var result = new Object();
	
	var latVal = mapDecodeInt(code.substr(0, 5));
	result.lat = (latVal / 1000000.0) - 180.0;

	var lonVal = mapDecodeInt(code.substr(5, 5));
	result.lon = (lonVal / 1000000.0) - 180.0;

	return result;
}

function mapDecodeInt(code) {
	var result = 0;
	for (var i = code.length - 1; i >= 0; i--)
	{
		var charNo = _mapEncodeChars.indexOf(code.substr(i, 1));
		if (charNo < 0 || charNo >= _mapEncodeChars.length) return 0;
		result = result * _mapEncodeChars.length + charNo;
	}
	return result;
} 

