window.onload = main;


var getOffsetX = function(e)
{
        var n = 0;
        do { n += e.offsetLeft; }
        while ( (e = e.offsetParent) );
        return n;
};

var getOffsetY = function(e)
{
        var n = 0;
        do { n += e.offsetTop; }
        while ( (e = e.offsetParent) );
        return n;
};

Number.prototype.toAngle = function()
{
    var n = ((this%1)+1)%1; // range from 0 to 1
    
    n = n*360;
    
    var west = false;
    
    if (n > 180)
    {
        west = true;
        n = 360 - n;
    }
    
    return (west ? '-' : '+') + ' ' + (n>>0) + '° ' + (Math.round((n%1)*600)/10) + "'";
    
    
};

var places = {
    London : [(7/60)/360 ,  -51.5 / 360 ],
    Sydney : [ (151+17/60)/360, (33+55/60)/360 ],
    Oslo   : [ (10+41/60)/360, -(59+56/60)/360 ]
}

var TPI = 2*Math.PI; // two-pi

Number.prototype.toMiller = function()
{
    return 5/4*Math.log(Math.tan(Math.PI/4 + 2/5*this));
};
Number.prototype.fromMiller = function()
{
    return 5/2*Math.atan(Math.pow(Math.E, 4/5*this)) - 5/8*Math.PI;
};

function main()
{
    var map = document.getElementById('map');
    
    if (!map.getContext)
    {
        alert('This demo requires a browser that supports Canvas such as Opera 9+, Firefox 1.5+, Safari 1.3+');
        return;
    }
    
    var ctx = map.getContext('2d');
    
    var points = [
        [(151+17/60)/360, (33+55/60)/360],
        [(7/60)/360 ,  -51.5 / 360]
    ];
    drawPoints();
        
    map.onmousedown = function(event)
    {
        var x = event.offsetX;
        var y = event.offsetY;
        
        var X,Y;
        
        for (var i=0; i<points.length; i++)
        {
            
            X = (points[i][0]+0.5)*800;
            
            Y = points[i][1];
            Y = (Y*TPI).toMiller() / (0.25*TPI).toMiller()/2;
            Y = (Y+0.5)*587;
            
            // pythagoras
            if ( 20*20 > (x-X)*(x-X) + (y-Y)*(y-Y))
            {
                dragPoint(i, event);
                return;
            }
        }
    }
    
    function dragPoint(i, event)
    {
        var downX = event.clientX;
        var downY = event.clientY;
        
        var startX = (points[i][0]+0.5)*800;

        var startY = points[i][1];
            startY = (startY*TPI).toMiller() / (0.25*TPI).toMiller()/2;
            startY = (startY+0.5)*587;
        
        document.onmousemove = function(event)
        {
            var lon = (startX + event.clientX - downX)/800+Math.random()/1000;
            
            var lat = (startY + event.clientY - downY)/587+Math.random()/1000;

            lat = lat < 0 ? 0 : lat > 1 ? 1 : lat;
            lon = (lon%1+1)%1;
            
            lon = lon-0.5;
            lat = lat-0.5;
            
            lat = (lat*TPI).fromMiller()/TPI * 0.87;
          
            points[i][0] = lon;
            points[i][1] = lat;
            
            drawPoints();
        };
        document.onmousemove(event);
        document.onmouseup = function(event)
        {
            document.onmousemove = null;
            document.onmouseup = null;
        };
    }

    function drawPoints()
    {
                  
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        
        drawCurve();
        ctx.fillStyle = 'red';
        
        var radius = 7;
        var str = "";
        
        var x,y;
        
        for (var i=0; i<points.length; i++)
        {

            x = points[i][0];
            y = points[i][1];
            
            y = (y*TPI).toMiller() / (0.25*TPI).toMiller()/2;

            x = x*800+400;

            y = (y+0.5)*587;
            
            ctx.beginPath();
            ctx.moveTo(x+radius, y);
            ctx.arc(x, y, radius, 0, Math.PI*2, true);
            ctx.fill();
            ctx.stroke();
            
            str += '<br>'+(i+1)+' = '+points[i][0].toAngle() + ', ' + points[i][1].toAngle();
        }
        

        /*
        ctx.fillStyle = 'lime';
        
        radius = 3;
        
        for (var i in places)
        {
            
            x = places[i][0];
            y = places[i][1];
            
            y = (y*TPI).toMiller() / (0.25*TPI).toMiller()/2;

            x = x*800+400;

            y = (y+0.5)*587;
            
            ctx.beginPath();
            ctx.moveTo(x+radius, y);
            ctx.arc(x, y, radius, 0, Math.PI*2, true);
            ctx.fill();
        }

       */


    }
    
    function drawCurve()
    {
      drawJoin();
    }
    
    function drawCircle()
    {
        var samples = 200;
        
        var x0 = Math.sin(points[0][0]*TPI) * Math.cos(points[0][1]*TPI);
        var y0 = Math.sin(points[0][1]*TPI);
        var z0 = -Math.cos(points[0][0]*TPI) * Math.cos(points[0][1]*TPI);
        
        var x1 = Math.sin(points[1][0]*TPI) * Math.cos(points[1][1]*TPI);
        var y1 = Math.sin(points[1][1]*TPI);
        var z1 = -Math.cos(points[1][0]*TPI) * Math.cos(points[1][1]*TPI);
    
    
    }
    
    function drawJoin()
    {
        var samples = 1000;
        
        var x0 = Math.sin(points[0][0]*TPI) * Math.cos(points[0][1]*TPI);
        var y0 = Math.sin(points[0][1]*TPI);
        var z0 = -Math.cos(points[0][0]*TPI) * Math.cos(points[0][1]*TPI);
        
        var x1 = Math.sin(points[1][0]*TPI) * Math.cos(points[1][1]*TPI);
        var y1 = Math.sin(points[1][1]*TPI);
        var z1 = -Math.cos(points[1][0]*TPI) * Math.cos(points[1][1]*TPI);
        
        var dist = Math.sqrt((x0-x1)*(x0-x1) + (y0-y1)*(y0-y1) + (z0-z1)*(z0-z1)); 
        
        var earth = 6372.795477598; //6378.1
        
        var km = (2*Math.asin(dist/2)*earth);
        var miles = km * 0.621371192;
        
        km = Math.round(10*km)/10;
        km = km + (km%1 ? ' km' : '.0 km');
        
        miles = Math.round(10*miles)/10;
        miles = miles + (miles%1 ? ' miles' : '.0 miles');
        
        document.getElementById('out').innerHTML = km + '<br>'+miles;
        
        ctx.strokeStyle = '#fff';
        ctx.beginPath();
        
        var x = 0; 
        var y = 0;
        var z = 0;
        
        var off = 0;  // 0 -> 1
        
        var rad = 0, lon, lat;
        
        var X, Y; 
        
        var lastX;
                    ctx.beginPath();
        for (var i=0; i<samples; i++)
        {
          var off = i/samples;
          x = x0*(1-off) + x1*off;
          y = y0*(1-off) + y1*off;
          z = z0*(1-off) + z1*off;
          
          rad = Math.sqrt(x*x+y*y+z*z);
          
          lat = Math.asin(y/rad);
          lon = Math.asin(x / (rad*Math.cos(lat)));
          
          if (z>0)
          {
            lon = -lon-Math.PI;
          }

            X =  (lon/TPI);
            Y =  (lat/TPI)
            
            Y = (Y*TPI).toMiller() / (0.25*TPI).toMiller()/2;

            X += 0.5;
            Y += 0.5;
    
              X = ((X%1+1)%1);
            Y = ((Y%1+1)%1);
    
            X = X*800;
            Y = Y*587;
          
          if (i==0 || Math.abs(X-lastX) > 400)
          {
            ctx.moveTo(X,Y);
          }
          else
          {
            ctx.lineTo(X,Y);
          }
          
          lastX = X;

  
        }
        ctx.lineWidth = 2;

        ctx.stroke();
    }
    
}
