﻿//Drawing tool
document.write("<script type='text/javascript' src='JavaScript/VMShape.js'></script>");
var slDrawing = null;
var myGeomType = null;

var myCurrentShape = null;
var myPoints = new Array();
var myDistance = 0;

var myPerimeter = 0;

var tempShape = null;
var tempPoints = new Array();
var tempDistance = 0;

var myCirclePoints = null;
var tempCircle = null;
var shapeCnt = 1;      //count the number of shapes

var currentLatLng = null;   //once in draw mode every single move is converted to latlng
var currentX = null;
var currentY = null;

var mapDivId = "MapPanel";
var divShapeInfo = "divShapeInfo";
var divDistance = "divDistance";
var divContext = "divContext";

var shapeUnfinished = false;

var kmToMileFactor = 0.6214;
var mile = "Miles";
var km = "Km";	
var distancePrecision = 3;      //3 digit after decimal

var vmShapeList = new VMShapeList();

var shapeIconURL = "";




//Initialization for drawing. This is called when page loaded
function DrawingInit(){
    slDrawing = new VEShapeLayer();
    map.AddShapeLayer(slDrawing);
}

function Draw(geomType, theIconURL)
{    
    shapeIconURL = theIconURL;
    myGeomType = geomType;
    try {
        detachDefaultMouseEvents();
        changeToDrawCursor();
        map.AttachEvent("onmousemove", MouseMove);
        map.AttachEvent("onclick", MouseClick);   
        map.AttachEvent("ondoubleclick", finishShape);                        
    } catch (ex) {
        //alert (ex.message);
    }
}
function endDrawing (){
    try {
        changeToPanCursor();  
        attachDefaultMouseEvents();
        map.DetachEvent("onmousemove", MouseMove);        
        map.DetachEvent("onclick", MouseClick);
        map.DetachEvent("onmousemove", drawOnMouseMove);
        map.DetachEvent("ondoubleclick", finishShape);     
        
        //clean up
        displayDiv(divContext, false);    
              
        
        displayDiv(divDistance, false);    
        
        //need to clean up the array to
        if (shapeUnfinished){
            removeShape(tempShape);            
        }
        myPoints = new Array();
        tempPoints = new Array();
        myDistance = 0;
        tempDistance = 0;  
          
        
    } catch (ex) {        
        //alert (ex.message);
    }
}

//Actions on mouse move. This action is detach only when user end drawing mode
function MouseMove(e)
{    
    changeToDrawCursor();
    updatePositionValues(e);    
    updateLatLngDisplay(currentLatLng.Latitude, currentLatLng.Longitude); 
    
    //un-commented this to enable auto pan         
    //autoPan(); 
}
function autoPan(){
    if (!isInsideMapView(currentX, currentY, map)){
        map.PanToLatLong(currentLatLng);
    }
}
//on every click
function MouseClick(e)
{    
    changeToDrawCursor();
    updatePositionValues(e); 
    //If Left mouse click -> drawing
    if (e.leftMouseButton){
        //if this is the first left click of a new shape
        //switch from mouse only to drawing on mouse move
        if (isNewShapeFirstClick()){                
             map.DetachEvent("onmousemove", MouseMove); 
             map.AttachEvent("onmousemove", drawOnMouseMove); 
             myPoints = new Array();
             tempPoints= new Array(); 
             
             myDistance = 0;
             tempDistance = 0;
             
             //add this point to both array             
             myPoints.push(currentLatLng);
             tempPoints.push(currentLatLng);
             
             displayDiv(divShapeInfo,false);
             
            
        }else {        
            if (myGeomType != "circle"){
                myPoints.push(currentLatLng);            
            }
        }
        
        //if draw pushin -> finish on every single left click
        if (myGeomType == "point"){
            finishShape();
        }
        
        updateDistanceOnMouseClick();        
        return;
    }
    
    //if Right mouse click -> show contex menu
    if (e.rightMouseButton){
        //showing the context div, must be 3 offset to make sure the mouse is in the 
        //context menu right way so the mouse move event of the map is not fired        
        //showContextMenu(currentX, currentY,3);
        showElementWithinMap("divContext", currentX, currentY, 3, false);
        
        return;
    }
    changeToDrawCursor();
}

//just draw the temp shape
function drawOnMouseMove(e){
    
    try {
        updatePositionValues(e);    
        updateLatLngDisplay(currentLatLng.Latitude, currentLatLng.Longitude);      
        
        //autoPan(); 
        
        
        var length = myPoints.length;
        
        tempPoints[length] = currentLatLng;
        
        updateTempShape();
        
        updateDistanceOnMouseMove();
        
        updateDistanceBox (tempDistance);
        //displayDiv(divDistance, true, currentX, currentY, 20);    
        showElementWithinMap(divDistance,currentX, currentY,20, true);
        
        
    } catch (ex){
        //alert (ex.message);
        
    }
    
}

function updateTempShape(){
    //delete the old one
    shapeUnfinished = true;
    removeShape(tempShape);
    
    var length = tempPoints.length;
    //draw the new one
    switch (myGeomType) 
        {
            case "polygon":
                if (length > 2){
                    tempShape = new VEShape(VEShapeType.Polygon, tempPoints);
                }else{
                    tempShape = new VEShape(VEShapeType.Polyline, tempPoints);
                }
                break;
            case "polyline":
                if (length > 1){
                tempShape = new VEShape(VEShapeType.Polyline, tempPoints);
                }
                break;
            case "circle":
                var distance = getDistance(tempPoints[0],tempPoints[length - 1]);                
                myCirclePoints = getCircle(tempPoints[0],distance);     
                if (myCirclePoints.length > 1){               
                    tempShape = new VEShape(VEShapeType.Polygon, myCirclePoints);                
                }
                break;            
        }
    tempShape.HideIcon();
    slDrawing.AddShape(tempShape);   
    
    
}

function finishShape(e){
    
    displayDiv(divContext,false);
    if (!shapeUnfinished & myGeomType != "point"){
        return;
    }
   
    
    
    i = i + 1;  
    
    myPoints = tempPoints;
    removeShape(tempShape);   
    
    //distance
    myDistance = tempDistance;
    displayDiv("divDistance",false);
    switch (myGeomType) 
        {
            case "polygon":
                myCurrentShape = new VEShape(VEShapeType.Polygon, myPoints);
                updateShapeDetails("Perimeter: " + cutOffDecimal(myDistance, distancePrecision) + " " + getDistanceUnit());
                updateVEShapeType(VEShapeType.Polygon);
                myCurrentShape.HideIcon();
                break;
            case "polyline":
                myCurrentShape = new VEShape(VEShapeType.Polyline, myPoints);
                updateShapeDetails("Distance: " + cutOffDecimal(myDistance, distancePrecision) + " " + getDistanceUnit());
                updateVEShapeType(VEShapeType.Polyline);
                myCurrentShape.HideIcon();
                break;
            case "circle":                
                myCurrentShape = new VEShape(VEShapeType.Polygon, myCirclePoints);
                updateShapeDetails("Radius: " + cutOffDecimal(myDistance, distancePrecision) + " "+ getDistanceUnit());
                updateVEShapeType(VEShapeType.Polygon);
                myCurrentShape.HideIcon();
                break;
            case "point":
                myCurrentShape = new VEShape(VEShapeType.Pushpin, currentLatLng);
                //uncomment this to include lat lng in the push pin
                //updateShapeDetails("Lat:" + cutOffDecimal(currentLatLng.Latitude, 6) + " Lng:" + cutOffDecimal(currentLatLng.Longitude, 6));
                updateVEShapeType(VEShapeType.Pushpin);
                break;
        }
        
    slDrawing.AddShape(myCurrentShape);  
    
    
        
        
    
    //updating the values shapeInfo div
    updateShapeId(randomString(10));  
    updateAppShapeType(shapeIconURL);     
    document.getElementById("txtShapeWKT").value = veshape2WKT(myCurrentShape);    
    document.getElementById("txtShapeTitle").value = "Untitled Shape " + shapeCnt;
    shapeCnt++;
    
    showElementWithinMap ('divShapeInfo',currentX, currentY,1, false); 
    shapeUnfinished = false;
    
    endDrawing();
    
    /********* This is for finishing shape still in drawing mode
    map.DetachEvent("onmousemove", drawOnMouseMove); 
    map.AttachEvent("onmousemove", MouseMove);  
    
    //clean up the myPoints and tempPoints
    myPoints = new Array();
    tempPoints = new Array();
    myDistance = 0;
    tempDistance =0;    
    
    changeToDrawCursor();
    ****************************/
    
    //this return will disable the zoom in when ondoubleclick in default VE map 
    if (e){
        return true;
    }
    return;
}


function updateDistanceOnMouseMove(){
    tempDistance = getTotalDistance(tempPoints, myGeomType);   
}

function updateDistanceOnMouseClick(){    
    myDistance = tempDistance;
}

function isNewShapeFirstClick(){
    return myPoints.length ==0;
}
/*
function addPointFromUserForm(){
    var latStr = document.getElementById("txtLat").value;
    var lngStr = document.getElementById("txtLon").value;
    
    if (isNaN(latStr) | isNaN(lngStr)){
        alert ("Input values for latitude and/or longitude is not valid number!");
        return;    
    }
    if (latStr !="" & lngStr !=""){            
        var lat = latStr*1;
        var lng = lngStr*1;
        if (lat < -90 | lat > 90 | lng < -180 | lng > 180){
            alert ("Input values for latitude and/or longitude is not valid range!");
            return;
        }    
        addPointByLatLng(latStr*1, lngStr*1);
    }            
}
function addPointByLatLng(lat, lng){
    //try {       
        var latLng = new VELatLong(lat, lng);
        
        myCurrentShape = new VEShape(VEShapeType.Pushpin, latLng);          
        
        //updating the values shapeInfo div        
        updateShapeDetails("Lat:" + cutOffDecimal(lat,6) + " Lng:" + cutOffDecimal(lng,6));                
        slDrawing.AddShape(myCurrentShape);   
        
        shapeIconURL = document.getElementById('linkDrawPoint').src;
         //updating the values shapeInfo div
        updateVEShapeType(VEShapeType.Pushpin);
        updateShapeId(randomString(10));  
        updateAppShapeType(shapeIconURL);     
        document.getElementById("txtShapeWKT").value = veshape2WKT(myCurrentShape);    
        document.getElementById("txtShapeTitle").value = "Untitled Shape " + shapeCnt;
        shapeCnt++;
        currentX = map.LatLongToPixel(latLng).x;
        currentY = map.LatLongToPixel(latLng).y;
        
        displayDiv ('divShapeInfo',true,currentX, currentY);  
    
    //} catch (ex){
       //alert(ex.message);
    //}    
    
}
*/
//calculate distance
function getDistance(p1, p2) 
{
    p1Lat = latLonToRadians(p1.Latitude);
	p1Lon = latLonToRadians(p1.Longitude);
	
	p2Lat = latLonToRadians(p2.Latitude);
	p2Lon = latLonToRadians(p2.Longitude);	
	
	var R = 6378.137; // 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 (getDistanceUnit() ==mile){
	    return disKm * kmToMileFactor;
	}
	return (disKm);
}//convert lat/long in degrees to radians
function latLonToRadians(point) 
{
	return point * Math.PI / 180;	
}//Draw Circle
function getCircle(center, distance)
{
    var R = 6371; // earth's mean radius in km
    if (getDistanceUnit() ==mile){
	    R = R * kmToMileFactor;
	}
    var lat = (center.Latitude * Math.PI) / 180; //rad
    var lon = (center.Longitude * Math.PI) / 180; //rad
    var d = parseFloat(distance) / R;  // d = angular distance covered on earth's surface
    var circlePoints = new Array();
    for (x = 0; x <= 360; x += 2) 
    { 
        var p2 = new VELatLong(0,0)            
        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;
        circlePoints.push(p2);
    }
    return circlePoints;
}
function getDistanceUnit(){
    if (document.getElementById("rdMile").checked == true){
        return mile;
    }
    return km;
}
function saveShape()
{   
    
    displayDiv('divShapeInfo', false);
    var id = document.getElementById("txtShapeId").value;
    var name = document.getElementById("txtShapeTitle").value;
    
    var details = document.getElementById("txtShapeDetails").value ;    
    var wkt = document.getElementById("txtShapeWKT").value;
    var appShapeType = document.getElementById("txtAppShapeType").value;
    
    
    
    //theId, theName, theDetails, theWKT, theVEShapeType, theAppShapeType
    vmShapeList.addShapeWithVEObj(id, name, details, wkt, myCurrentShape, appShapeType);    
   
    
    myPoints = new Array();
    tempPoints = null;
    myDistance = 0;
    tempDistance = 0;
    
    
    
    //document.getElementById("divShapeInfo").style.visibility = "hidden";    
    
}

function cancelSaveShape(){
    saveShape();
    /*
    displayDiv('divShapeInfo', false);
    //removeShape(myCurrentShape);    
    myPoints = new Array();
    tempPoints = null;
    myDistance = 0;
    tempDistance = 0;
    */
}

function DeleteShapeById(shapeId)
{   
    try {
        var delShape = slDrawing.GetShapeByID(shapeId);    
        if (delShape){
            removeShape(delShape);
            hideInfoBox();
        }    
    }catch (ex){
        //alert ("Error: DeleteShapeById method: " + ex.message);
    }  
}

function removeShape(shape){    
    try {
        if (shape){
            slDrawing.DeleteShape(shape);
        }
    }catch (ex){
        //alert (ex.message);
    }  
}







//undo last point only apply for drawing shapes that is polygon or polyline
function undoLastVertex(){
    displayDiv(divContext, false);
    if (myGeomType == "point"){        
        return;
    }
    
    if (myPoints.length ==0){
        displayDiv("divDistance", false);            
        return;
    }
    
    myPoints.pop();
    
    //remove the second last;
    var length = tempPoints.length;
    var last = tempPoints[length];    
    tempPoints.pop();
    tempPoints.pop();
    //pushback to last
    tempPoints.push(last);
    
    //if pop the last point
    if (myPoints.length ==0 ){
        try {        
            displayDiv("divDistance", false);                        
            //removeShape(tempShape);            
            //removeShape(myCurrentShape);   
                        
            tempPoints = new Array();
            myDistance = 0;
            tempDistance = 0;
            
            
            Draw(myGeomType);         
        } catch (ex){
            //alert (ex.message);
        }
        
    }
}

function getTotalDistance(arr, shapeType){
    var d = 0;
    var length = arr.length;
    if (shapeType =="circle"){
        return getDistance (arr[0], arr[length-1]);
    }else {
    
        for (var i = 0; i< length-1; i++){
            var latlng1 = arr[i];
            var latlng2 = arr[i+1];
            d = d + getDistance (latlng1, latlng2);
        }
        if (shapeType =="polygon"){
            d = d + getDistance (arr[0], arr[length-1]);    
        }
        return d;
    }
}
function displayDivByObj(theDiv, visible, x, y, theOffset){
    var offset = null;
    
    if (visible == false){
        //old way
        //theDiv.style.visibility = "hidden";
        
        //new way        
        theDiv.style.display = "none";
                
        return;
    }    
    if (!theOffset){
        offset = 0; //display div offset from input x, y
    }else {
        offset = theOffset;
    }
    
    if (x !=null & y !=null){
        if (!isNaN(x) || !isNaN(y)){     
        theDiv.style.left = (x + offset + map.GetLeft()) + "px";
        theDiv.style.top = (y + offset + map.GetTop())  + "px";
        }
    }
    if (visible == true){
        //old way
        //theDiv.style.visibility = "visible"; 
        
        //new way
        theDiv.style.display = "block"; 
        
        
    }
    window.setTimeout("noOp();");
    
}
//x, y are the pixel the coordinates in the map (not in the screen)
function displayDiv(divId, visible, x, y, theOffset){
    var theDiv = document.getElementById(divId);    
    displayDivByObj(theDiv,visible, x, y, theOffset);
    
}

function updateDistanceBox (value){
    document.getElementById("txtDistance").value = cutOffDecimal(value, distancePrecision) + " " + getDistanceUnit() ;
}

function updateLatLngDisplay(lat, lng){
    document.getElementById("txtLat").value = cutOffDecimal(lat, 6);
    document.getElementById("txtLon").value = cutOffDecimal(lng, 6);
}

function updateShapeId(value){
    document.getElementById("txtShapeId").value = value;
}
function updateShapeDetails(value){
    document.getElementById("txtShapeDetails").value = value;
}
function updateAppShapeType(shapeType){
    document.getElementById("txtAppShapeType").value = shapeType;
}
function updateVEShapeType(shapeType){
    document.getElementById("txtVEShapeType").value = shapeType;
}

function setScaleBarToMile(){
    map.SetScaleBarDistanceUnit(VEDistanceUnit.Miles);
}
function setScaleBarToKm(){
    map.SetScaleBarDistanceUnit(VEDistanceUnit.Kilometers);
}
function updatePositionValues(e){
    currentX = e.mapX;
    currentY = e.mapY;
    var pixel = new VEPixel(currentX, currentY);
    currentLatLng =  map.PixelToLatLong(pixel);
}
function getCurrentLatLng(e){
    var x = e.mapX;
    var y = e.mapY;
    var pixel = new VEPixel(x, y);
    return map.PixelToLatLong(pixel);
}

function isInsideMapView(x, y, theMap){
    var bound = theMap.GetMapView();
    var topLeft = bound.TopLeftLatLong;
    var bottomRight = bound.BottomRightLatLong;
    
    var tolerance = 5; // if cursor is 5 pixels close to the boundary;
    
    var topLeftPixel = map.LatLongToPixel(topLeft)
    var minX = topLeftPixel.x + tolerance;
    var minY = topLeftPixel.y + tolerance;
    
    var bottomRightPixel = map.LatLongToPixel(bottomRight);    
    var maxX = bottomRightPixel.x - tolerance;
    var maxY = bottomRightPixel.y - tolerance;
    
    
    
    if ((x > maxX) | (x < minX) | (y > maxY) | (y < minY)){    
        return false;
    }
    return true;
    
}

/************* cursor *************************/
function changeToDrawCursor(){
    document.getElementById(mapDivId).style.cursor='crosshair';
}

function changeToPanCursor (){
    document.getElementById(mapDivId).style.cursor='http://maps.live.com/cursors/grab.cur';
}

/****** zooming **********************/

function addToZoomLevel(value){
    var z = map.GetZoomLevel();
    z = z + value;
    if (z < 17 & z > 0){        
        map.SetZoomLevel(z);
    }    
}

function centerMapHere(){
    displayDiv(divContext,false);
    map.SetCenter (currentLatLng);
}

function showShapeInfoPanel(){    
    document.getElementById("divShapeInfo").style.visibility = "visible";
    document.getElementById("divShapeInfo").style.display = "block";
    document.getElementById('divShapeInfo').className = "SavePanelShow";
    
}
function hideShapeInfoPanel(){
    document.getElementById("divShapeInfo").style.visibility = "hidden";
    document.getElementById("divShapeInfo").style.display = "none";
    
}

//showing an element within the mapview. 
//Offset : positive number of pixel away from theX, and theY
//away: the offset make theX and theY always away or inside the element


function showElementWithinMap(theId, theX, theY, theOffset, away){
    if (theX < 0){
        theX = 0;
    }
    if (theY < 0){
        theY = 0;
    }
    var contextH = getEleHeight(theId);
    var contextW = getEleWidth(theId);    
    
    
    var mapH = getEleHeight("MapPanel");
    var mapW = getEleWidth("MapPanel");
    
    //if not away-> means inside, substract offset to make mouse is inside
    if (away == false){
        theOffset = -1*theOffset;
    }
    var showX= theX + theOffset ;
    var showY = theY + theOffset;
    
    var lowerRightX = showX + contextW ;
    var lowerRightY = showY + contextH ;
    
    if (lowerRightX > mapW ){
        //if out, offset must be added to make mouse inside context menu
        showX = Math.min(mapW, showX) - contextW - theOffset;
    }
    if (lowerRightY > mapH){
        showY = Math.min(mapH, showY) - contextH - theOffset;
    }
    
    displayDiv(theId,true,showX,showY,0);
}
/* -------context menu-------------------- */





