var OS = {};

OS = {

//convert northing and easting to letter and number grid system
 NE2NGR_wtp: function( east,  north)
{
var eX = east / 500000;
var nX = north / 500000;
var tmp = Math.floor(eX) - 5.0 * Math.floor(nX) + 17.0; 
nX = 5 * (nX - Math.floor(nX));
eX = 20 - 5.0 * Math.floor(nX) + Math.floor(5.0 * (eX - Math.floor(eX)));
if (eX > 7.5) eX = eX + 1; // I is not used
if (tmp > 7.5) tmp = tmp + 1; // I is not used

var eing = east - (Math.floor(east / 100000)*100000);
var ning = north - (Math.floor(north / 100000)*100000);
var estr = eing.toFixed(0);
var nstr = ning.toFixed(0);
while(estr.length < 5)
	estr = "0" + estr;
while(nstr.length < 5)
	nstr = "0" + nstr;

var ngr = String.fromCharCode(tmp + 65) + 
          String.fromCharCode(eX + 65) + 
          " " + estr + " " + nstr;
return ngr;
},

 NGR2NE_wtp: function(ngr){
var e;
var n;

ngr = ngr.toUpperCase(ngr);

var bits = ngr.split(' ');
ngr = "";
for(var i=0;i<bits.length;i++)
    ngr+=bits[i];

var c = ngr.charAt(0);
if (c =='S'){ 
    e = 0;
    n = 0;
    }
else if (c == 'T'){
    e = 500000;
    n = 0;
    }
else if (c == 'N'){ 
    n = 500000;
    e = 0;
    }
else if (c == 'O'){
    n = 500000;
    e = 500000;
    }
else if(c == 'H'){
    n = 1000000;
    e = 0;
    }
else 
    return null;
    
c = ngr.charAt(1);
if(c == 'I')
    return null;
    
c = ngr.charCodeAt(1) - 65;
if(c > 8)
    c -= 1;
e += (c % 5) * 100000;
n += (4 - Math.floor(c/5)) * 100000;

c = ngr.substr(2);
if ((c.length%2) == 1) 
    return null;
if (c.length > 10) 
    return null;

 try{
    var s = c.substr(0,c.length/2);
    while(s.length < 5)
        s += '0';
    e += parseInt(s,10); 
    if(isNaN(e))
        return null; 
    
    s = c.substr(c.length/2);
    while(s.length < 5)
        s += '0';
    n += parseInt(s,10); 
    if(isNaN(n))
        return null;
        
    //return new OpenSpace.MapPoint(e,n);
	return new OpenLayers.LonLat(e,n);
 }
 catch (ex)
 {
    return null;
 }

}
} // end OS

var pGradientColours = new Array();
var nGradientColours = new Array();

function RGB2Color(r,g,b)
{
  return '#' + byte2Hex(r) + byte2Hex(g) + byte2Hex(b);
}

function byte2Hex(n)
{
  var nybHexString = "0123456789ABCDEF";
  return String(nybHexString.substr((n >> 4) & 0x0F,1)) + nybHexString.substr(n & 0x0F,1);
}

function initGradientColours() {

    var f = Math.PI/4;

    for (var i = 0; i < 4; ++i)
    {
       red   = Math.sin(f*i + 0) * 127 + 128;
       green = Math.sin(f*i + (Math.PI/2) ) * 127 + 128;
       blue = 0;
       pGradientColours.push(RGB2Color(red,green,blue));
       red = 0;
       green = Math.sin(f*-i + Math.PI/2) * 127 + 128;
       blue  = Math.sin(f*-i + (Math.PI) ) * 127 + 128;
       nGradientColours.push(RGB2Color(red,green,blue));
    }
}


 // UNUSED
 //makes nodes description for GPX
 function makeMkrDescription(m,bDirections,bNotes){

    var d = ""
    
	
	if(bDirections){
    	d += "Grid: " + NE2NGR_wtp(m.lonlat.lon,m.lonlat.lat);
    	//if(gEPlugin != null){
    	//    var pt = m.gMkr.getPoint();
        //    var alt = gEPlugin.getGlobe().getGroundAltitude(pt.lat(),pt.lng());
        //    d += " Alt: " + alt.toFixed(0) + "m";    	    
    	//} 
	    if(m.pred){
	        d += " From Start: " + distanceToString(m.dFromStart);
	        if(m.naismithFromStart)
	            d += ", " + mins2string(m.naismithFromStart);
	    }
	    if(m.succ){
	        d += " To End: " + distanceToString(m.dToEnd);
  	        if(m.naismithToEnd)
	            d += ", " + mins2string(m.naismithToEnd);
	        d += " To Next: " + distanceToString(m.dToNext);
   	        if(m.naismithMins)
	            d += ", " + mins2string(m.naismithMins);
	        d += ", " + m.bToNext + " degrees";
	        
	        if(m.bTerrain){
	            d += ", Ascent " + m.ascent + "m, Descent " + m.descent + "m";
	            d += ", MaxGradient " + m.maxGradient + ", MinGradient " + m.minGradient;
	        }
	    }
	    else{
	        if(m.bTerrain)
	            d += ", Total Ascent " + m.ascent + "m, Total Descent " + m.descent + "m";
	            d += ", Surface Distance " + distanceToString(m.surfaceDistance);
	    }
	    if(m.pred)
	        d += " From Previous: " + distanceToString(m.dToPrev) + ", " + m.bToPrev + "degrees";
	}
	

    return d;

 }


var OL = {};

OL = {
 bearingBetween: function(p1, p2){
   var b = Math.atan2(p2.y-p1.y,p2.x-p1.x);//pi to -pi
   b *= 180/Math.PI; 
   b -= 90;//maths to compass
   b = 360-b;
   if(b < 0)
        b += 360;
   if(b >= 360)
        b -= 360;
   return b.toFixed(0);
 }
} // end open layers

var OSRoute = {};

OSRoute = {	
  // DEPENDS ON: UKTerrain (this is a callback)
  // DEPENDS ON: RoutePlanner (HTML, calculateSummary)
  gotAlt: function(d)
  {
    if(d){
        if(d.id){
            var i;
            for(i=0; i<osTrackMkrs.length; i++){
                if(osTrackMkrs[i].uid == d.id){

                    var c;
                    var oMkr = osTrackMkrs[i];
                
                    if((d.maxGradient > 10)||(d.maxGradient < -10) ||
                       (d.minGradient > 10)||(d.minGradient < -10)){
                        oMkr.bTerrain = false; 
                        c = "#FF00FF";                      
                    }
                    else
                    {                                        
                        oMkr.ascent = d.ascent;
                        oMkr.descent = d.descent;
                        oMkr.maxGradient = d.maxGradient;
                        oMkr.minGradient = d.minGradient;
                        oMkr.surfaceDistance = d.surfaceDistance;
                        oMkr.sparkline = d.sparkline;
                        oMkr.bTerrain = true;
                        
                        //Naismith time
                        oMkr.naismithMins = (d.surfaceDistance / (speed * 1000)) * 60;
                        oMkr.naismithMins += (oMkr.ascent / 600) * 60;
                        if(d.minGradient < 0){ 
                            if((d.minGradient < -0.0874) && (d.gradient > -0.2126))
                                // 5 to 12 degrees down
                                oMkr.naismithMins -= (d.descent / 300) * 10;
                            else if(d.gradient < -0.2126)
                                // > 12 degrees down
                                oMkr.naismithMins += (d.descent / 300) * 10;
                        }
                        
                        
                    
                        //colour the links
                        
                        if(pGradientColours.length == 0)
                            initGradientColours();
                            
                        var cUp;
                        var cDown;
                        var rd = 1/d.maxGradient;
                        if(rd >= 10)
                            s = 0;
                        else if (rd >= 6)
                            s = 1;
                        else if (rd >= 3)
                            s = 2;
                        else 
                            s = 3;                                                            
                        cUp = pGradientColours[s];                         

                        var rd = -1/d.minGradient;
                        if(rd >= 10)
                            s = 0;
                        else if (rd >= 6)
                            s = 1;
                        else if (rd >= 3)
                            s = 2;
                        else 
                            s = 3;    

                        cDown = nGradientColours[s]; 
                        
                        if((d.ascent == 0) && (d.descent == 0))
                            c = "#00FF00";
                        else if(d.ascent > d.descent)
                            c = cUp;
                        else if(d.descent > d.ascent)
                            c = cDown;
                        else if(d.maxGradient == (-d.minGradient))
                            c = "#00FF00";                        
                        else if(d.maxGradient > (-d.minGradient))
                            c = cUp;                                                                            
                        else
                            c = cDown;                               
                    }
                    
                    oMkr.linkColour = c;     
                    OSRoute.colourLink(oMkr,c);   


			// TODO factor this out into RoutePlanner application, along with calculateSummary() call

            // update route card HTML
            var hg = document.getElementById("p-" + oMkr.succ.uid + "-hg");
            hg.innerHTML = oMkr.ascent;
            var tfl = document.getElementById("p-" + oMkr.succ.uid + "-tfl");
            tfl.innerHTML = mins2string(oMkr.naismithMins.toFixed(0));
			tHg += oMkr.ascent;
			tMins += oMkr.naismithMins;
			
			
			var elTHg = document.getElementById("total-hg");
			elTHg.innerHTML = tHg;
			var elTMins = document.getElementById("total-tfl");
			elTMins.innerHTML = mins2string(tMins.toFixed(0));
                                                                                                           
                    break;
                } 
            }         
            document.documentElement.firstChild.removeChild(document.getElementById('jsonTerrainScript' + d.id));

			RoutePlanner.calculateSummary();

        }
    }
  }, // end function

  linkOsPoints: function(oMkr) {
	 var tkLine1 =
         {
             strokeColor: "#FF0000",
             strokeOpacity: 0.75,
             strokeWidth: 3
         };
	 var tkLine2 =
         {
             strokeColor: "#FF0000",
             strokeOpacity: 0.75,
             strokeWidth: 3
         };

	if(oMkr.pred){
		if (oMkr.pred.link)
			vectorLayer.removeFeatures([oMkr.pred.link]);
		var pts = new Array();
		pts.push(new OpenLayers.Geometry.Point(oMkr.pred.lonlat.lon,oMkr.pred.lonlat.lat));
		pts.push(new OpenLayers.Geometry.Point(oMkr.lonlat.lon,oMkr.lonlat.lat));
	        var lineString = new OpenLayers.Geometry.LineString(pts);
		oMkr.pred.link = new OpenLayers.Feature.Vector(lineString, null, {strokeColor: "#FF00FF",  strokeOpacity: 0.75, strokeWidth: 4 });		
	        vectorLayer.addFeatures([oMkr.pred.link]);
	        
	    // get details of terrain for pred 
        //UKTerrain.getTerrain(oMkr.pred.lonlat.lon,oMkr.pred.lonlat.lat,oMkr.lonlat.lon,oMkr.lonlat.lat,oMkr.pred);
 
	}

	if(oMkr.succ){
		if (oMkr.link)
			vectorLayer.removeFeatures([oMkr.link]);
		var pts = new Array();
		pts.push(new OpenLayers.Geometry.Point(oMkr.succ.lonlat.lon,oMkr.succ.lonlat.lat));
		pts.push(new OpenLayers.Geometry.Point(oMkr.lonlat.lon,oMkr.lonlat.lat));
	        var lineString = new OpenLayers.Geometry.LineString(pts);
		oMkr.link = new OpenLayers.Feature.Vector(lineString, null, {strokeColor: "#FF00FF",  strokeOpacity: 0.75, strokeWidth: 4 });		
	        vectorLayer.addFeatures([oMkr.link]);
	        
	        
	    // get details of terrain to next
        //UKTerrain.getTerrain(oMkr.lonlat.lon,oMkr.lonlat.lat,oMkr.succ.lonlat.lon,oMkr.succ.lonlat.lat,oMkr);
	    
	    
	}

	
  },

 // links OS markers and calculates distances and bearings between nodes
  linkOsMarkers: function(oMkr) {
	 var tkLine1 =
         {
             strokeColor: "#FF0000",
             strokeOpacity: 0.75,
             strokeWidth: 3
         };
	 var tkLine2 =
         {
             strokeColor: "#FF0000",
             strokeOpacity: 0.75,
             strokeWidth: 3
         };

	if(oMkr.pred){
		if (oMkr.pred.link)
			vectorLayer.removeFeatures([oMkr.pred.link]);
		var pts = new Array();
		pts.push(new OpenLayers.Geometry.Point(oMkr.pred.lonlat.lon,oMkr.pred.lonlat.lat));
		pts.push(new OpenLayers.Geometry.Point(oMkr.lonlat.lon,oMkr.lonlat.lat));
	        var lineString = new OpenLayers.Geometry.LineString(pts);
		oMkr.pred.link = new OpenLayers.Feature.Vector(lineString, null, {strokeColor: "#FF00FF",  strokeOpacity: 0.75, strokeWidth: 4 });		
	        vectorLayer.addFeatures([oMkr.pred.link]);
	        
	    // get details of terrain for pred 
        UKTerrain.getTerrain(oMkr.pred.lonlat.lon,oMkr.pred.lonlat.lat,oMkr.lonlat.lon,oMkr.lonlat.lat,oMkr.pred);
 
	}

	if(oMkr.succ){
		if (oMkr.link)
			vectorLayer.removeFeatures([oMkr.link]);
		var pts = new Array();
		pts.push(new OpenLayers.Geometry.Point(oMkr.succ.lonlat.lon,oMkr.succ.lonlat.lat));
		pts.push(new OpenLayers.Geometry.Point(oMkr.lonlat.lon,oMkr.lonlat.lat));
	        var lineString = new OpenLayers.Geometry.LineString(pts);
		oMkr.link = new OpenLayers.Feature.Vector(lineString, null, {strokeColor: "#FF00FF",  strokeOpacity: 0.75, strokeWidth: 4 });		
	        vectorLayer.addFeatures([oMkr.link]);
	        
	        
	    // get details of terrain to next
        UKTerrain.getTerrain(oMkr.lonlat.lon,oMkr.lonlat.lat,oMkr.succ.lonlat.lon,oMkr.succ.lonlat.lat,oMkr);
	    
	    
	}

	var m = osTrackMkrs[0];
	m.dToNext = 0;
	m.dFromStart = 0;
	m.bToNext = null;
	m.dToPrev = null;
	m.bToPrev = null;	
 	var d = 0;
 	var l;
 	var i=0;
	var p1 = new OpenLayers.Geometry.Point(m.lonlat.lon,m.lonlat.lat);

	while(m.succ){

	    var p2 = new OpenLayers.Geometry.Point(m.succ.lonlat.lon,m.succ.lonlat.lat);

		l = p1.distanceTo(p2);
		m.dToNext = l;
		m.bToNext = OL.bearingBetween(p1,p2);		
		m.dFromStart = d;
		m.index = i++;
		d += l;
		
		m = m.succ;	

	    if(m.pred != null)
	    {
    		m.dToPrev = l;
	    	m.bToPrev = OL.bearingBetween(p2,p1);		
	    }
	    
		p1 = p2;
	}
	m.dFromStart = d;
	m.index = i;
	document.getElementById("txtTrack").value = distanceToString(d);
	
	while(m.pred){
	    m.dToEnd = d - m.dFromStart; 
	    m = m.pred;
	}
 	m.dToEnd = d - m.dFromStart; 
  }, // end function

  colourLink: function (oMkr, c){
	
	if(oMkr.succ){
	    if(oMkr.link){
	        oMkr.link.style.strokeColor = c;
	        vectorLayer.redraw();
	    }
	}
	
    // set asc + desc of final node etc
    var m = osTrackMkrs[0];
    var totalAscent = 0;	
    var totalDescent = 0;
    var totalSurface = 0;
    var totalNaismith = 0;
    var bAll = true;
    while(m.succ){
        if((m.bTerrain) && (bAll)) {
            totalAscent += m.ascent;
            totalDescent += m.descent;
            totalSurface += m.surfaceDistance;    
            m.naismithFromStart = totalNaismith;
            totalNaismith += m.naismithMins;
        }
        else{
            bAll = false;    
            m.naismithFromStart = 0;
        }
        m = m.succ;
    }
    while(m.pred){
        if(m.naismithFromStart)
            m.naismithToEnd = totalNaismith - m.naismithFromStart;	                 
        else
            m.naismithToEnd = 0;
        m = m.pred;
    }
    m = osTrackMkrs[0]
    m.naismithToEnd = totalNaismith - m.naismithFromStart;
    
    m = osTrackMkrs[osTrackMkrs.length-1];
    if(bAll){
        m.bTerrain = true;
        m.ascent = totalAscent;
        m.descent = totalDescent;
        m.naismithFromStart = totalNaismith;
        m.surfaceDistance = totalSurface;
		//document.getElementById("txtTrack").value = distanceToString(m.dFromStart) + ", " + mins2string(totalNaismith);
    }
    else{
		//document.getElementById("txtTrack").value = distanceToString(m.dFromStart);
        m.naismithFromStart = 0;
        m.bTerrain = false;
    }
  }, // end function

  getPreviousLeg: function(id) {
	if (osTrackLegs.length == 0) {
		return -1;
	}
	var previous = osTrackLegs[0];
	for (var i = 1;i < osTrackLegs.length;i++) {
		var cur = osTrackLegs[i];
		if (id == cur) {
			return previous;
		}
		previous = cur;
	}
	return -1;
  },

  removeLeg: function(id) {
	osTrackLegs.remove(id);
  },

  markAsLeg: function(id) {
	// add id to legs array
	osTrackLegs.push(id);
	// sort legs array
	osTrackLegs.sort(function(a,b){return a - b});
	//alert(osTrackLegs);
  },

  isLeg: function(id) {
	for (var i=0;i < osTrackLegs.length;i++) {
		if (osTrackLegs[i]==id) {
			return true;
		}
	}
	return false;
  }

} // end OSRoute


var UKTerrain = {};

UKTerrain = {
getTerrain: function(e, n, e2, n2, oMkr)
{
    /*if( (((e-e2)*(e-e2)) + ((n-n2)*(n-n2))) < (50*50) ){
        oMkr.bTerrain = false;
        oMkr.naismithMins = 0;
        oMkr.naismithFromStart = 0;
        oMkr.naismithToEnd = 0;
        colourLink(oMkr,"#FF00FF");     
        return;
    }*/

    // TODO replace this with a prototype AJAX call rather than injecting html and js

    var script = document.createElement('script');
    script.setAttribute('src', 'http://ukterrain.appspot.com/?e=' + parseInt(e) + "&n=" + parseInt(n) + 
                                "&e2=" + parseInt(e2) + "&n2=" + parseInt(n2) + 
                                "&id=" + oMkr.uid + '&callback=OSRoute.gotAlt');
    script.setAttribute('id', 'jsonTerrainScript' + oMkr.uid);
    script.setAttribute('type', 'text/javascript');
    document.documentElement.firstChild.appendChild(script);
}

}




