/*
 * Flightplanner. Copyright (c) Stefan Wallström 2007-2010
 *
 */

var debugtmp;
var fplgmap;
var map;
var fplSearchedNavaids = new Array();
var fplPlan = new Array();
var fplDocTitle = '';
var fplExtra = { };

var oldSearchText;
var currentSearchText;
var currentSearchReq;

var fplusetoc;
var fpltoclat;
var fpltoclong;

var fplgicons = { };

function is_ie() {
 if(YAHOO.env.ua.ie && YAHOO.env.ua.ie > 0.0) {
   return 1;
 }
 return 0;
}

function my_parse(s, forDisplay) {
  var val = parseFloat(s.replace(',','.'));
  if(isNaN(val)) {
   if(forDisplay)
     return 0;
   return 0.0;
  }
  return val;
}

function searchPressed() {
  window.setTimeout(searchPressedLow, 10);
  return true;
}

function searchPressedLow() {
  var cur_txt = $('#searchText').val();
  if (cur_txt != oldSearchText) {
    oldSearchText = cur_txt;
    if (currentSearchReq) {
      window.clearTimeout(currentSearchReq);
      currentSearchReq = 0;
    }
    if (cur_txt.length < 1) {
       $('#fplsearchrespane').html('');
    } else {
      currentSearchText = cur_txt;
      currentSearchReq =
        window.setTimeout(searchPressedLowLow, 500);
    }
  }
  return true;
}



function searchPressedLowLow() {
  var val = currentSearchText;


  $('#searchSpinner').show();
  $.ajax( {
		url:'search.xml',
		dataType:'json',
                success: searchCallback,
                error: searchCallbackE,
                data: {'name': val, magic_roxen_automatic_charset_variable : 'åäö&#x829f;' }
             });
  return false;
}



function searchCallbackE(XMLHttpRequest, textStatus, errorThrown) {
  $('#searchSpinner').hide();
  alert('Error when retrieving data from the server!');
}

function searchCallback(json) {
  $('#searchSpinner').hide();

   var srHtml='';          
   for(i = 0; i < json.length; i++) {
        var na = json[i];
        var oNavaid = new Navaid(na['kind'],na['code'],na['name'],na['lat'],na['long'],na['hash'],na['distance']);
        srHtml = srHtml + oNavaid.srHtml();
        fplSearchedNavaids[oNavaid.hash] = oNavaid;
     }
     if(srHtml == '')
	 srHtml = '<br /><i>Inga träffar</i>';
     $('#fplsearchrespane').html(srHtml);
}

function searchrangeCallback(json) {
 
   var currenthash = fplPlan[current_edit_leg].navaid ? fplPlan[current_edit_leg].navaid.hash : '';

   var srangeHtml='';          
   var addednavaids = 0;
   for(i = 0; i < json.length; i++) {
        var na = json[i];
        var oNavaid = new Navaid(na['kind'],na['code'],na['name'],na['lat'],na['long'],na['hash'],na['distance']);
        fplSearchedNavaids[oNavaid.hash] = oNavaid;
        if(oNavaid.hash != currenthash) {
          srangeHtml = srangeHtml + oNavaid.srangeHtml(current_edit_leg);
          addednavaids++;
        }
     }
     $('#editlegwpts').html(srangeHtml);
     if(addednavaids > 0)
       $('#editlegwptsblock').show();
     else
       $('#editlegwptsblock').hide();

}


function sortedPlan() {
   var seq = new Array();
   var items = jQuery('#fplplanpane li.waypoint'); 
   for (i=0;i<items.length;i=i+1) { 
      var id = items[i].id ; 
      var num = parseInt(id.replace('waypoint_',''),10);
      seq.push(num);
   }
 
   var newplan = [ ];
   for(i=0; i < seq.length; i++) {
     newplan[i] = fplPlan[seq[i]-1];
  }

   //FIXME: leg conf?

  fplPlan = newplan;
  if(fplPlan.length > 0)
    fplSetDirty(1);
  else
    fplSetDirty(0);
  fplDisplayPlan();
  fplDrawPlan();
}



function fplDeleteAll() {
   if(fplisdirty == 1) {
     if(!confirm('Du förlorar nuvarande färdplan. Fortsätta?'))
        return;
   }

   fplPlan = new Array();
   fplExtra = { };
   fplSetDirty(0);
   fplSetDocTitle('');
   fplDisplayPlan();
   fplDrawPlan();
}


function fplReversePlan() {
   for(i = 1; i < fplPlan.length ; i++) {
     fplPlan[i-1].copyLegConf(fplPlan[i]);
   }
   fplPlan.reverse();
  if(fplPlan.length > 0)
    fplSetDirty(1);
  else
    fplSetDirty(0);
   fplDisplayPlan();
   fplDrawPlan();
}

function waypointIcon(wp, align, style) {

    var kind2 = null;
   
    if(!wp.navaid)
       return '<img style="'+style+'" align="'+align+'" src="gfx/gps.gif"/>';

    switch(wp.navaid.kind) {
      case 'ndb':
      case 'apt':
      case 'vor':
        kind2 = wp.navaid.kind;
        break;
      case 'fix':
        kind2 = 'intersection';
        break;
    }

    if(kind2 != null)
     return '<img style="'+style+'" align="'+align+'" src="gfx/'+kind2+'.gif"/>';
    else
     return '';
  }


var current_edit_leg; //FIXME: remove


function fplDeleteCurrentLeg() {
  fplRemoveFromPlan(current_edit_leg);
  fpleditlegdlg.hide();
}

function fplEditLeg(idx) {
  fpleditlegdlg.show();
  current_edit_leg = idx;

  var legend = '';

  legend = legend +  waypointIcon(fplPlan[current_edit_leg], 'middle','');
  legend = legend + ' ' + fplPlan[current_edit_leg].describe(0);
  $('#editleglegend').html(legend);

  $('input#tas').val(fplPlan[current_edit_leg].tas);
  $('input#wd').val(fplPlan[current_edit_leg].wd);
  $('input#ws').val(fplPlan[current_edit_leg].ws);
  $('input#var').val(fplPlan[current_edit_leg].vari);
  if(fplPlan[current_edit_leg].description)
    $('input#description').val(fplPlan[current_edit_leg].description);
  else
    $('input#description').val('');

  $('#tasall').removeAttr('checked');
  $('#wdall').removeAttr('checked');
  //$('wsall').removeAttr('checked');
  $('#varall').removeAttr('checked');

  if(!fplPlan[current_edit_leg].navaid)
    $('#editlegconfblock2').show();
  else
    $('#editlegconfblock2').hide();


  if(current_edit_leg == 0) {
    $('#editlegconfblock').hide();

    if(!fplPlan[current_edit_leg].navaid)
       $('#editlegconfblock3').show();
    else
       $('#editlegconfblock3').hide();
  }
  else {
    $('#editlegconfblock').show();
    $('#editlegconfblock3').show();
  }

  $('#editlegwpts').html('');
  $.ajax( {
		url:'searchrange.xml',
		dataType:'json',
                success: searchrangeCallback,
                data: {'reference-lat': fplPlan[idx].getLat(), 'reference-long':fplPlan[idx].getLong(),'distance-limit':10.0,'name':'*' }
             });

}

function fplRemoveFromPlan(idx) {
   var newPlan = new Array();
   for(i = 0; i < fplPlan.length ; i++) {
     if(i != idx)
        newPlan.push(fplPlan[i]);
   }
   fplPlan = newPlan;
  if(fplPlan.length > 0)
    fplSetDirty(1);
  else
    fplSetDirty(0);
   fplDisplayPlan();
   fplDrawPlan();
}


function fplUpdateWaypointLatLong(idx, lat, lng) {
   fplPlan[idx].setLatLong(lat, lng);
   fplSetDirty(1);
   fplDisplayPlan();
   fplDrawPlan();
}

function bestInsertPoint(lat, lng) {
   var xtds = new Array();
   var lastWaypoint;

   var foundidx = -1;
   var minxtd = 0.0;

   for(i = 0; i < fplPlan.length ; i++) {
     var oWaypoint = fplPlan[i];

     if(lastWaypoint) {
       var xtd_atd = calc_xtd_atd(lastWaypoint.getLat(),lastWaypoint.getLong(),oWaypoint.getLat(),oWaypoint.getLong(), lat, lng); 
       var frac = xtd_atd[2];
       var xtd = xtd_atd[0];
       var absxtd = Math.abs(xtd);
       var dist = xtd_atd[3];
       var ok = ((frac > -0.20 && frac < 1.20) && ( (absxtd / dist) < 0.5) ? 1 : 0);
       if(ok) {
         if(foundidx < 0) {
           foundidx = i;
           minxtd = absxtd;
         } else if(absxtd < minxtd){
           foundidx = i;
           minxtd = absxtd;
         }
       }
       xtds.push( { 'xtd': xtd,'atd':xtd_atd[1],'frac':frac, 'ok':ok, 'absxtd':absxtd}  );
     }
    lastWaypoint = oWaypoint;
   }

   if(foundidx < 0 && fplPlan.length > 1) {
       var dist1 =  calc_dist_track(fplPlan[0].getLat(),fplPlan[0].getLong(), lat, lng)[0]; 
       var dist2 =  calc_dist_track(fplPlan[fplPlan.length - 1].getLat(),fplPlan[fplPlan.length - 1].getLong(), lat, lng)[0]; 
       if(dist1 < dist2)
        foundidx = 0;
   }
   if(foundidx == 1 && fplPlan.length > 1) {
       var dist =  calc_dist_track(fplPlan[0].getLat(),fplPlan[0].getLong(), lat, lng)[0]; 
       if(dist < 0.0001) // point is same as first point, append to last to make a roundtrip
        foundidx = -1;
   }
   if(foundidx == fplPlan.length-1 && fplPlan.length > 1) {
       var dist =  calc_dist_track(fplPlan[fplPlan.length - 1].getLat(),fplPlan[fplPlan.length - 1].getLong(), lat, lng)[0]; 
       if(dist < 0.0001) // point is same as first point, insert as first point to make a roundtrip
        foundidx = 0;
   }

  return foundidx;

}

function fplAddNavaidToPlan(hash) {
   var oNavaid = fplSearchedNavaids[hash]
   var newWaypoint = new Waypoint();
   newWaypoint.setNavaid(oNavaid);

   var foundidx = bestInsertPoint(newWaypoint.getLat(), newWaypoint.getLong());

   if(foundidx < 0) {
     fplPlan.push (newWaypoint);
     if(fplPlan.length > 1)
       fplPlan[fplPlan.length - 1].copyLegConf(fplPlan[fplPlan.length - 2]);
   } else {
     var newPlan = new Array();
     for(i = 0; i < fplPlan.length ; i++) {
       if(i == foundidx) {
          newPlan.push(newWaypoint);
          if(i == 0) {
            if(fplPlan.length > 1)
             fplPlan[0].copyLegConf(fplPlan[1])
          }
          else 
            newWaypoint.copyLegConf(fplPlan[i]);
       }
       newPlan.push(fplPlan[i]);
     }
     fplPlan = newPlan;
   }

   fplgmaptmpshow(newWaypoint.getLat(), newWaypoint.getLong());
   fplSetDirty(1);
   fplDisplayPlan();
   fplDrawPlan();
}

function fplReplaceWithNavaid(idx,hash) {
   var oNavaid = fplSearchedNavaids[hash]

   var newWaypoint = new Waypoint();
   newWaypoint.setNavaid(oNavaid);
   
   var oldWaypoint = fplPlan[idx];
   fplPlan[idx] = newWaypoint;
   fplPlan[idx].copyLegConf(oldWaypoint);

   fplSetDirty(1);
   fplDisplayPlan();
   fplDrawPlan();
}


function fplMapClick(lat, lng) {
   var newWaypoint = new Waypoint();
   newWaypoint.setLatLong(lat,lng);
   var foundidx = bestInsertPoint(lat, lng);

   if(foundidx < 0) {
     fplPlan.push (newWaypoint);
     if(fplPlan.length > 1)
       fplPlan[fplPlan.length - 1].copyLegConf(fplPlan[fplPlan.length - 2]);
   } else {
     var newPlan = new Array();
     for(i = 0; i < fplPlan.length ; i++) {
       if(i == foundidx) {
          newPlan.push(newWaypoint);
          if(i == 0) {
            if(fplPlan.length > 1)
             fplPlan[0].copyLegConf(fplPlan[1])
          }
          else 
            newWaypoint.copyLegConf(fplPlan[i]);
       }
       newPlan.push(fplPlan[i]);
     }
     fplPlan = newPlan;
   }

   fplgmaptmpshow(newWaypoint.getLat(), newWaypoint.getLong());
   fplSetDirty(1);
   fplDisplayPlan();
   fplDrawPlan();
}

var fplPlanOverlays = [ ];
      
function fplClearPlanOverlays() {
  fplgmap.closeInfoWindow();
  for(i = 0; i < fplPlanOverlays.length ; i++) {
     fplgmap.removeOverlay(fplPlanOverlays[i]);
   }
   fplPlanOverlays = [ ];
}


function createWpMarker(i,point, icontype) {
  var marker = new GMarker(point, {draggable: true, icon: fplgicons[icontype]});
  GEvent.addListener(marker, "click", function() {
      fplEditLeg(i);
  });
  GEvent.addListener(marker, "dragend", function() {
    fplUpdateWaypointLatLong( i, marker.getPoint().lat(), marker.getPoint().lng());
  });
  return marker;
}

      
function fplDrawPlan() {
  fplClearPlanOverlays();
  var lastPoint;
  for(i = 0; i < fplPlan.length ; i++) {
    var point = new GPoint(fplPlan[i].getLong(), fplPlan[i].getLat());
    var marker = createWpMarker(i,point,fplPlan[i].icontype());

    fplPlanOverlays.push(marker);
    //GEvent.addListener(marker , "click", function() {
    //  fplPlanOverlays[fplPlanOverlays.length-1].openInfoWindowHtml(html);
    // });
     map.addOverlay(marker);

    if(i != 0) {
      var polyline = new GPolyline([lastPoint,point],"#d000d0", 5, 1 , {geodesic:true} );
      map.addOverlay(polyline);
      fplPlanOverlays[fplPlanOverlays.length] = polyline;
    }
    lastPoint = point;
  }

  if(fplusetoc) {
   var point = new GPoint(fpltoclong, fpltoclat);
   var icon = fplgicons['toc'];

   var marker = new GMarker(point, icon);
   GEvent.addListener(marker, "click", function() {
 	//marker.openInfoWindowHtml('TOC');
        fplfueldlgShow();
    });
    fplPlanOverlays.push(marker);
    map.addOverlay(marker);
  }

}

function editedLegData() {
 
  var tas =  parseInt($('input#tas').val() ,10);
  var wd =  parseInt($('input#wd').val(), 10);
  var ws =  parseInt($('input#ws').val(), 10);
  var vari =  parseInt($('input#var').val(), 10);
  var description =  $('input#description').val();

  if(current_edit_leg != 0) {
    if($('#tasall').attr('checked') == true) {
       for(i = 0; i < fplPlan.length ; i++)
       fplPlan[i].tas = tas;
    } 
    else
       fplPlan[current_edit_leg].tas = tas;

    if($('#wdall').attr('checked') == true) {
       for(i = 0; i < fplPlan.length ; i++) {
         fplPlan[i].wd = wd;
         fplPlan[i].ws = ws;
       }
    } 
    else {
       fplPlan[current_edit_leg].wd = wd;
       fplPlan[current_edit_leg].ws = ws;
    }


    if($('#varall').attr('checked') == true) {
       for(i = 0; i < fplPlan.length ; i++)
       fplPlan[i].vari = vari;
    } 
    else
       fplPlan[current_edit_leg].vari = vari;
   }

  if(!fplPlan[current_edit_leg].navaid)
       fplPlan[current_edit_leg].description = description;
     

  fpleditlegdlg.hide();
  fplSetDirty(1);
  fplDisplayPlan();
}

function fplDisplayPlan(tripfuelonly) {
  var lastWaypoint;
  fplusetoc = false;

  if(!tripfuelonly)
    $('#printformcont').html('');
  var printitems = '';

  var olde = $('#fplplanpane > *');

  if(!tripfuelonly)
    olde.each( function() { $(this).remove(); } );

  var wptmpl = '<li class="#{class}" id="#{wpid}">#{desc1}<span id="#{wpid}_desc">#{desc2}</span><span style="position: absolute;right: 60px;"><a href="#" onClick="fplEditLeg(#{idx});return false;">Redigera</a> <a href="#" onClick="fplRemoveFromPlan(#{idx});return false;">Radera</a></span><br/>&nbsp;#{desc}</li>';
  var fplitems = '';

  var totDist = 0.0;
  var totTime = 0.0;
  var totFuel = 0.0;

  var tmpprefix = '';
  if(tripfuelonly)
     tmpprefix = '_';

  var fuelavg = my_parse($('#'+tmpprefix+'fuelavg').val());

  var usetoc;
  if(tripfuelonly)
    usetoc = $('#_usetoc').attr('checked');
  else
    usetoc = $('#usetoc').val() == '1' ? true : false;
  var toctime = my_parse($('#'+tmpprefix+'fueltoctime').val()) * 60.0;
  var tocdist = my_parse($('#'+tmpprefix+'fueltocdist').val());
  var tocfuel = my_parse($('#'+tmpprefix+'fueltocfuel').val());
  var toctas;
  if(toctime < 0.01 || tocdist < 0.01)
    usetoc = 0;
  if(usetoc)
    toctas =  tocdist / (toctime / 3600.0);
  var insertedtoc = !usetoc;

  for(i = 0; i < fplPlan.length ; i++) {
    var oWaypoint = fplPlan[i];


    var desc1 =  waypointIcon(fplPlan[i], 'top','float: left') + '&nbsp;' ;
 
    var desc2 = fplPlan[i].describe(0);
	//FIXME: escape

   var desc = '';
   var tas = fplPlan[i].tas;


   var dist,track,dist_track;
   if(i > 0) {
     dist_track = calc_dist_track(lastWaypoint.getLat(),lastWaypoint.getLong(),oWaypoint.getLat(),oWaypoint.getLong());
     dist = dist_track[0];
     track = dist_track[1];
   }

   if(i> 0 && !insertedtoc) {
    var gs_t_th_wca = calc_wind( toctas,fplPlan[i].wd,fplPlan[i].ws, track, dist);

    if(gs_t_th_wca[1] >= toctime) {
      // toc is in this leg
      //console.log('toc is in this leg',i);
      var climbgroundmiles = gs_t_th_wca[0] * toctime/(3600);

      var toc_lat_long = calc_intermediate_point(fplPlan[i-1].getLat(),fplPlan[i-1].getLong(),fplPlan[i].getLat(),fplPlan[i].getLong(), climbgroundmiles/dist,dist);

      fplusetoc = true;
      fpltoclat = toc_lat_long[0];
      fpltoclong = toc_lat_long[1];

      //console.log('groundmiles in climb', climbgroundmiles);

      totDist = totDist + climbgroundmiles;
      totTime = totTime + toctime;
      totFuel = totFuel + tocfuel;

      var tocdesc = '';

      tocdesc = tocdesc + ' W/V: ' + fplPlan[i].wd + '/' + fplPlan[i].ws;

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 160px;">';
       tocdesc = tocdesc + ' TAS: ' + toctas.toFixed(0);
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 220px;">';
       tocdesc = tocdesc + ' TT: ' + track.toFixed(0);
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 275px;">';
       tocdesc = tocdesc + ' dist: ' + climbgroundmiles.toFixed(1);
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 340px;">';
       tocdesc = tocdesc + ' ack.dist: ' + totDist.toFixed(1);
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 430px;">';
       tocdesc = tocdesc + ' gs: ' + gs_t_th_wca[0].toFixed(0);
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 490px;">';
       tocdesc = tocdesc + ' wca: ' + gs_t_th_wca[3].toFixed(0);
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 550px;">';
       tocdesc = tocdesc + ' th: ' + gs_t_th_wca[2].toFixed(0);
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 600px;">';
       tocdesc = tocdesc + ' var: ' + fplPlan[i].vari;
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 650px;">';
       tocdesc = tocdesc + ' mh: ' + (gs_t_th_wca[2].toFixed(0) - fplPlan[i].vari);
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 710px;">';
       tocdesc = tocdesc + ' t: ' + formatTime(toctime);
       tocdesc = tocdesc + '</span>';

       tocdesc = tocdesc + '<span style="white-space:nowrap;position:absolute; left: 760px;">';
       tocdesc = tocdesc + ' ack.t: ' + formatTime(totTime);
       tocdesc = tocdesc + '</span>';

       printitems = printitems + '<input type="hidden" name="desc" value="TOC"/>'; 
       printitems = printitems + '<input type="hidden" name="tas" value="'+ toctas.toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="wd" value="'+fplPlan[i].wd+'"/>'; 
       printitems = printitems + '<input type="hidden" name="ws" value="'+fplPlan[i].ws+'"/>'; 
       printitems = printitems + '<input type="hidden" name="var" value="'+fplPlan[i].vari+'"/>'; 
       printitems = printitems + '<input type="hidden" name="kind" value="toc"/>'; 
       printitems = printitems + '<input type="hidden" name="code" value=""/>'; 
       printitems = printitems + '<input type="hidden" name="tt" value="'+track.toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="dist" value="'+climbgroundmiles.toFixed(1)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="ackdist" value="'+totDist.toFixed(1)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="gs" value="'+gs_t_th_wca[0].toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="wca" value="'+gs_t_th_wca[3].toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="th" value="'+gs_t_th_wca[2].toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="mh" value="'+(gs_t_th_wca[2].toFixed(0) - fplPlan[i].vari)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="t" value="'+formatTime(toctime)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="ackt" value="'+formatTime(totTime)+'"/>'; 
 
       fplitems +=  '<li class="toc" id="toc"><img align="top" src="gfx/toc.gif" style="float: left;"/>&nbsp;TOC<br/>&nbsp;'+tocdesc+'</li>';

       dist_track = calc_dist_track( toc_lat_long[0], toc_lat_long[1], oWaypoint.getLat(), oWaypoint.getLong() );
       dist = dist_track[0];
       track = dist_track[1];

      
      insertedtoc = true;
    } else {
      // toc is in later leg, use climb tas for this leg
      tas = toctas;
      toctime -= gs_t_th_wca[1];
    }
   }


    printitems = printitems + '<input type="hidden" name="desc" value="'+fplPlan[i].describe(0)+'"/>'; 
    printitems = printitems + '<input type="hidden" name="tas" value="'+tas.toFixed(0)+'"/>'; 
    printitems = printitems + '<input type="hidden" name="wd" value="'+fplPlan[i].wd+'"/>'; 
    printitems = printitems + '<input type="hidden" name="ws" value="'+fplPlan[i].ws+'"/>'; 
    printitems = printitems + '<input type="hidden" name="var" value="'+fplPlan[i].vari+'"/>'; 
    if(fplPlan[i].navaid) {
      printitems = printitems + '<input type="hidden" name="kind" value="'+fplPlan[i].navaid.kind+'"/>'; 
      printitems = printitems + '<input type="hidden" name="code" value="'+fplPlan[i].navaid.code+'"/>'; 
    }
    else {
      printitems = printitems + '<input type="hidden" name="kind" value="gps"/>'; 
      printitems = printitems + '<input type="hidden" name="code" value=""/>'; 
    }

    if(lastWaypoint) {
       var gs_t_th_wca = calc_wind( tas,fplPlan[i].wd,fplPlan[i].ws, track, dist);
       totDist = totDist + dist;
       totTime = totTime + gs_t_th_wca[1];
       if(insertedtoc)
         totFuel = totFuel + gs_t_th_wca[1] / 3600.0 * fuelavg;

       desc = desc + ' W/V: ' + fplPlan[i].wd + '/' + fplPlan[i].ws;

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 160px;">';
       desc = desc + ' TAS: ' + tas.toFixed(0);
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 220px;">';
       desc = desc + ' TT: ' + track.toFixed(0);
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 275px;">';
       desc = desc + ' dist: ' + dist.toFixed(1);
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 340px;">';
       desc = desc + ' ack.dist: ' + totDist.toFixed(1);
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 430px;">';
       desc = desc + ' gs: ' + gs_t_th_wca[0].toFixed(0);
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 490px;">';
       desc = desc + ' wca: ' + gs_t_th_wca[3].toFixed(0);
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 550px;">';
       desc = desc + ' th: ' + gs_t_th_wca[2].toFixed(0);
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 600px;">';
       desc = desc + ' var: ' + fplPlan[i].vari;
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 650px;">';
       desc = desc + ' mh: ' + (gs_t_th_wca[2].toFixed(0) - fplPlan[i].vari);
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 710px;">';
       desc = desc + ' t: ' + formatTime(gs_t_th_wca[1]);
       desc = desc + '</span>';

       desc = desc + '<span style="white-space:nowrap;position:absolute; left: 760px;">';
       desc = desc + ' ack.t: ' + formatTime(totTime);
       desc = desc + '</span>';


       printitems = printitems + '<input type="hidden" name="tt" value="'+dist_track[1].toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="dist" value="'+dist_track[0].toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="ackdist" value="'+totDist.toFixed(1)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="gs" value="'+gs_t_th_wca[0].toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="wca" value="'+gs_t_th_wca[3].toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="th" value="'+gs_t_th_wca[2].toFixed(0)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="mh" value="'+(gs_t_th_wca[2].toFixed(0) - fplPlan[i].vari)+'"/>'; 
       printitems = printitems + '<input type="hidden" name="t" value="'+formatTime(gs_t_th_wca[1])+'"/>'; 
       printitems = printitems + '<input type="hidden" name="ackt" value="'+formatTime(totTime)+'"/>'; 

    } else {
       printitems = printitems + '<input type="hidden" name="tt" value=""/>'; 
       printitems = printitems + '<input type="hidden" name="dist" value=""/>'; 
       printitems = printitems + '<input type="hidden" name="ackdist" value=""/>'; 
       printitems = printitems + '<input type="hidden" name="gs" value=""/>'; 
       printitems = printitems + '<input type="hidden" name="wca" value=""/>'; 
       printitems = printitems + '<input type="hidden" name="th" value=""/>'; 
       printitems = printitems + '<input type="hidden" name="mh" value=""/>'; 
       printitems = printitems + '<input type="hidden" name="t" value=""/>'; 
       printitems = printitems + '<input type="hidden" name="ackt" value=""/>'; 

    }

    var wpid = 'waypoint_' + (i+1).toString();

    fplitems = fplitems + $.tmpl(wptmpl, { 'class': 'waypoint', 'wpid': wpid, 'idx':''+i , 'desc1': desc1,'desc2': desc2,'desc': desc} );
    lastWaypoint = oWaypoint;
  }

   var fuelreserve = fuelavg * my_parse($('#'+tmpprefix+'fuelreserve').val()) / 60.0;
   var fueltaxi = my_parse($('#fueltaxi').val());
 
   printitems = printitems + '<input type="hidden" name="tottime" value="'+totTime+'"/>'; 
   printitems = printitems + '<input type="hidden" name="fuelavg" value="'+fuelavg+'"/>'; 
   printitems = printitems + '<input type="hidden" name="fuel" value="'+totFuel.toFixed(1)+'"/>'; 
   printitems = printitems + '<input type="hidden" name="fueltaxi" value="'+fueltaxi.toFixed(1)+'"/>'; 
   printitems = printitems + '<input type="hidden" name="fueltoc" value="'+tocfuel.toFixed(1)+'"/>'; 
   printitems = printitems + '<input type="hidden" name="reservetime" value="'+my_parse($('#fuelreserve').val()).toFixed(0)+'"/>'; 
   printitems = printitems + '<input type="hidden" name="usetoc" value="'+(usetoc?'1':'0')+'"/>'; 
   printitems = printitems + '<input type="hidden" name="fuelunit" value="'+$('#fuelunit').val()+'"/>'; 
   printitems = printitems + '<input type="hidden" name="fuelreserve" value="'+fuelreserve.toFixed(1)+'"/>'; 
   printitems = printitems + '<input type="hidden" name="fueltot" value="'+(totFuel + fueltaxi + fuelreserve).toFixed(1)+'"/>'; 

  if(!tripfuelonly) {
    $('#fplplanpane').html(fplitems);

    var ddtarget = new YAHOO.util.DDTarget("fplplanpane"); 
    for(i = 0; i < fplPlan.length ; i++) {
      var wpid = 'waypoint_' + (i+1).toString();
      var dditem = new DDList(wpid); 
        dditem.endDragEvent.subscribe(sortedPlan, wpid);
    }

    var atsplan = '';
    if( fplPlan.length > 2) {
      for(i = 1; i < fplPlan.length-1 ; i++) {
        atsplan += ' DCT ';
        atsplan = atsplan + fplPlan[i].atsdescribe();
      }
      atsplan += ' DCT';
    }
    $('#atsplan').html(atsplan);
    $('#printformcont').html(printitems);

    for(i = 0; i < fplPlan.length ; i++) {
      var oWaypoint = fplPlan[i];
      var wpid = 'waypoint_' + (i+1).toString();
/* FIXME: works unstable
      if(oWaypoint.navaid == null) {
        $('#'+wpid+'_desc').editable(function(value, settings) { 
         fplPlan[settings.i].description = value;
         return fplPlan[settings.i].describe(0);
        }, {
            'i' : i, 
            tooltip   : "Klicka för att ändra...",
            style  : "inherit",
          data: function(value, settings) { return fplPlan[settings.i].description; }
        });
      }
 */
    }
 
    resizeFplApp();
  } else {
    return totFuel;
  }
}


function fplgmaptmpshow(lat, lng) {
  fplgmap.recenterOrPanToLatLng(new GPoint(lng, lat));
}

var fplTmpMarker;

function fplShowTmpMarker(name,code,lat, lng) {
  if(fplTmpMarker)
    fplgmap.removeOverlay(fplTmpMarker);

  var point = new GPoint(lng, lat);
  var marker = new GMarker(point);

  var html = '<b>' + name + '</b> ('+code+')';
  GEvent.addListener(marker, 'click', function() {
    marker.openInfoWindowHtml(html);
  });
  fplgmap.addOverlay(marker);

  fplTmpMarker = marker;
    fplgmap.recenterOrPanToLatLng(point);
  }


var ctrOverlays = [ ];
var tmaOverlays = [ ];
var restrictedOverlays = [ ];

function ctrOverlayRemove () {
  for(i = 0; i < ctrOverlays.length; i++) {
    fplgmap.removeOverlay(ctrOverlays[i]);
   }
   ctrOverlays = [ ];
}

function tmaOverlayRemove () {
  for(i = 0; i < tmaOverlays.length; i++) {
     fplgmap.removeOverlay(tmaOverlays[i]);
  }
  tmaOverlays = [ ];
}

function restrictedOverlayRemove () {
  for(i = 0; i < restrictedOverlays.length; i++) {
    fplgmap.removeOverlay(restrictedOverlays[i]);
  }
  restrictedOverlays = [ ];
}

function ctrOverlay () {
  var overlay;
  for(j = 0; j < fplctr.length; j++) {
     var coords =[];
    if(fplctr[j][1] == 'polygon') {
      for(i = 0; i < fplctr[j][2].length; i++) {
        coords.push (new GLatLng (fplctr[j][2][i][0], fplctr[j][2][i][1]));
      }
    } else if(fplctr[j][1] == 'circle') {
         var lat = fplctr[j][2][0];
         var lng = fplctr[j][2][1];
         var rad = fplctr[j][2][2] / 1852.0;
         for( k = 0; k < 21 ; k++) {
          var lat_lng = calc_radial_dist(lat,lng, k*(360.0/ 20.0),rad)
          coords.push (new GLatLng (lat_lng[0], lat_lng[1]) );
         }
     }     
     overlay = new GPolygon (coords, "#000080", 2, 1, "#FF0000", 0.1);
     ctrOverlays.push(overlay);
     map.addOverlay(overlay);
  }
}

function tmaOverlay () {
  var overlay;
  for(j = 0; j < fpltma.length; j++) {
    var coords =[];
    if(fpltma[j][1] == 'polygon') {
      for(i = 0; i < fpltma[j][2].length; i++) {
        coords.push (new GLatLng (fpltma[j][2][i][0], fpltma[j][2][i][1]));
      }
    } else if(fpltma[j][1] == 'circle') {
         var lat = fpltma[j][2][0];
         var lng = fpltma[j][2][1];
         var rad = fpltma[j][2][2] / 1852.0;
         for( k = 0; k < 21 ; k++) {
          var lat_lng = calc_radial_dist(lat,lng, k*(360.0/ 20.0),rad)
          coords.push (new GLatLng (lat_lng[0], lat_lng[1]) );
         }
     }
    overlay = new GPolyline (coords, "#000080", 2, 1);
    tmaOverlays.push(overlay);
    map.addOverlay(overlay);
  }
}

function restrictedOverlay () {
  var overlay;
  for(j = 0; j < fplrestricted.length; j++) {
    var coords =[];
    if(fplrestricted[j][1] == 'polygon') {
      for(i = 0; i < fplrestricted[j][2].length; i++) {
        coords.push (new GLatLng (fplrestricted[j][2][i][0], fplrestricted[j][2][i][1]));
      }
    } else if(fplrestricted[j][1] == 'circle') {
         var lat = fplrestricted[j][2][0];
         var lng = fplrestricted[j][2][1];
         var rad = fplrestricted[j][2][2] / 1852.0;
         for( k = 0; k < 21 ; k++) {
          var lat_lng = calc_radial_dist(lat,lng, k*(360.0/ 20.0),rad)
          coords.push (new GLatLng (lat_lng[0], lat_lng[1]) );
         }
     }
    overlay = new GPolygon (coords, "#FF0000", 2, 1, "#FF0000", 0.2);
    restrictedOverlays.push(overlay);
    map.addOverlay(overlay);
  }
}

function resizeFplApp() {
  var fixed = $('#hd').height() +  $('#fplplan').height() + 40;
  var mainSize = $(window).height() - fixed;
  if(mainSize < 400)
    mainSize = 400;
  $('#fplmain').height(''+mainSize + 'px');
  $('#googlemap').height( ''+(mainSize-20) + 'px' );
  if(map)
    map.checkResize();
}

function splitLegs() {
  if(fplPlan.length < 2)
    return;

  var maxMins = parseFloat($('#leglength').val())
 
  if(maxMins < 10.0) {
    maxMins = 10.0; //sanity
     $('#leglength').val('10');
 }

  var i = 0;

  while(i < fplPlan.length-1) {

       var dist_track = calc_dist_track(fplPlan[i].getLat(),fplPlan[i].getLong(),fplPlan[i+1].getLat(),fplPlan[i+1].getLong());
       var wd = 0;
       var ws = 0;

       if($('#splitlegwind').val() == 'gs') {
          wd =fplPlan[i+1].wd;
          ws = fplPlan[i+1].ws;
       }
       var gs_t_th_wca = calc_wind( fplPlan[i+1].tas, wd, ws, dist_track[1], dist_track[0] );
       var legtime = gs_t_th_wca[1];
       var leggs = gs_t_th_wca[0];
       var legtrack = dist_track[1];

      if(legtime - 30.0 > maxMins * 60.0) { // 30 seconds grace
       var newleglength = leggs * (maxMins / 60.0);
       //var new_lat_long = calc_radial_dist(fplPlan[i].getLat(),fplPlan[i].getLong(),legtrack,newleglength);
       var new_lat_long = calc_intermediate_point(fplPlan[i].getLat(),fplPlan[i].getLong(),fplPlan[i+1].getLat(),fplPlan[i+1].getLong(),(maxMins*60.0)/legtime,dist_track[0]);


       var newWaypoint = new Waypoint();
       newWaypoint.setLatLong(new_lat_long[0],new_lat_long[1]);
       newWaypoint.copyLegConf(fplPlan[i+1]);
       var newPlan = new Array();
       for(j = 0; j < fplPlan.length ; j++) {
         if(i+1 == j)
           newPlan.push(newWaypoint);
         newPlan.push(fplPlan[j]);
         fplSetDirty(1);
       }
       fplPlan = newPlan;
       fplDisplayPlan();
       fplDrawPlan();

      }

     i+=1;
  }
 
  fplsplitlegdlg.hide();
}


var fpldisclaimerdlg;
var fplhelpdlg;
var fpleditlegdlg;
var fplsplitlegdlg;
var fplfueldlg;
var fplloaddlg;
var fplsavedlg;
var fplsharedlg;
var fpllogindlg;
var fplloadedfiles;
var fplafterloginfn;
var fplisdirty = 0;

function fplSetDirty(dirty) {
  fplisdirty = dirty;
  fplUpdateWindowTitle();
}

function fplSetDocTitle(title) {
  fplDocTitle = title;
  fplUpdateWindowTitle();
}

function fplUpdateWindowTitle() {
  document.title = 'LFK - Färdplanering - ' + fplDocTitle + (fplisdirty == 1 ? ' <ej sparad>' : '');
}

function  loginCallbackE(XMLHttpRequest, textStatus, errorThrown) {
  alert('Error loading data from the server!');
}

function loginCallback(json) {

   if(json.result=='ok') {
      fpllogindlg.hide();
      switch(fplafterloginfn) {
         case 'save':
          fplsave();
          break;
         case 'load':
          fplload();
          break;
         case 'share':
          fplshare();
          break;
     }
  

    $('#toolbox').load('/lfk-toolbox.xml');

   } else {
      $('#fplloginfailed').show();
   }

}

function  shareCallbackE(XMLHttpRequest, textStatus, errorThrown) {
  alert('Error loading data from the server!');
}

function shareCallback(json) {

   if(json.result != 'ok') {
     fplsharedlg.hide();
     fplafterloginfn = 'share';
     $('#fplloginfailed').hide();
     fpllogindlg.show();
     return;
   }

   //debugtmp = json;
   var html = '';
   fplloadedfiles = json.files;

   for(i=0; i < json.files.length; i++) {
  
    html += '<table><tr><td>';
    html += json.files[i].name ;
    html += '<br /><a target="_blank" href="http://www.lfk.se/flygning/planering/v2/?load='+json.files[i].secret+'">http://www.lfk.se/flygning/planering/v2/?load='+json.files[i].secret+'</a>';
    html += '<br/><span class="mini">Senast uppdaterad: '+json.files[i].modified +'</span>';
    html += '</td></tr></table>';
  }

  $('#sharefiles').html(html);
}

function  loadotherCallbackE(XMLHttpRequest, textStatus, errorThrown) {
  alert('Den länkade färdplanen är raderad och kunde inte laddas');
}

function loadotherCallback(json) {

   fplloadedfiles = json.files;
  if(json.files.length == 0) {
    alert('Den länkade färdplanen är raderad och kunde inte laddas');
  } else {
    fplloaddata(0);
 }
}

function  loadCallbackE(XMLHttpRequest, textStatus, errorThrown) {
  alert('Error loading data from the server!');
}

function loadCallback(json) {

   if(json.result != 'ok') {
     fplloaddlg.hide();
     fplafterloginfn = 'load';
     $('#fplloginfailed').hide();
     fpllogindlg.show();
     return;
   }

   //debugtmp = json;
   var html = '';
   fplloadedfiles = json.files;

   for(i=0; i < json.files.length; i++) {
  
    html += '<table><tr><td>';
    html += '<a class="blocklink" style="width: 550px;" href="#" onClick="fplloaddata('+i+');fplloaddlg.hide();return false;">';
    html += json.files[i].name ;
    html += '<br/><span class="mini">Senast uppdaterad: '+json.files[i].modified +'</span>';
    html += '</a>';
    html += '</td><td><img style="" src="'+fplDeleteButtonSrc+'"  onClick="return fplDeleteSavedPlan('+json.files[i].id+',0);"/>';
    html += '</td></tr></table>';
  }

  $('#loadfiles').html(html);
}

function  saveloadCallbackE(XMLHttpRequest, textStatus, errorThrown) {
  alert('Error loading data from the server!');
}

function saveloadCallback(json) {

   if(json.result != 'ok') {
     fplsavedlg.hide();
     fplafterloginfn = 'save';
     $('#fplloginfailed').hide();
     fpllogindlg.show();
     return;
   }

   //debugtmp = json;
   var html = '';
   fplloadedfiles = json.files;

   for(i=0; i < json.files.length; i++) {
  
    html += '<table><tr><td>';
    html += '<a class="blocklink" style="width: 550px;" href="#" onClick="fplselectsavefile('+i+');return false;">';
    html += json.files[i].name ;
    html += '<br/><span class="mini">Senast uppdaterad: '+json.files[i].modified +'</span>';
    html += '</a>';
    html += '</td><td><img style="" src="'+fplDeleteButtonSrc+'"  onClick="return fplDeleteSavedPlan('+json.files[i].id+',1);"/>';
    html += '</td></tr></table>';
  }

  $('#savefiles').html(html);
}


function fplloadotherplan(secret) {
 $.ajax( { 
	url:'loadother.xml',
        dataType: 'json',
        success: loadotherCallback,
        error: loadotherCallbackE,
        data: { 'secret':secret,magic_roxen_automatic_charset_variable : 'åäö&#x829f;' }
             });
}

function fplload() {
  if(fplisdirty == 1) {
    if(!confirm('Om du laddar in en färdplan så förlorar du den nuvarande'))
      return;
  }
  $('#loadfiles').html('');
  fplloaddlg.show();


  $.ajax( {
     		url: 'loadsave.xml',
		dataType: 'json',
                success: loadCallback,
                error: loadCallbackE,
                data: { magic_roxen_automatic_charset_variable : 'åäö&#x829f;' }
             });



}

function fplshare() {
  $('#sharefiles').html('');

  fplsharedlg.show();

  $.ajax( {
		url: 'loadsave.xml',
		dataType: 'json',
	        success: shareCallback,
                error: shareCallbackE,
                data: { magic_roxen_automatic_charset_variable : 'åäö&#x829f;' }
             });



}

function fpllogin() {
 
  $.ajax( {
		url:'login.xml',
		dataType:'json',
                success: loginCallback,
                error: loginCallbackE,
                data: { 
                        'username': $('input#username').val(),
                        'password': $('input#password').val(),                            
                        magic_roxen_automatic_charset_variable : 'åäö&#x829f;' }
             });



}


function fplDeleteSavedPlan(i, saveDlg) {
  if(confirm('Är du säker på att du vill radera den sparade färdplanen?')) {
  
    if(saveDlg == 1) {
     $.ajax( {
		url:'loadsave.xml',
 		dataType:'json',
                success: saveloadCallback,
                error: saveloadCallbackE,
                data: { "delete":i,magic_roxen_automatic_charset_variable : 'åäö&#x829f;' }
              });
    }
    else {
     $.ajax( {
		url:'loadsave.xml',
		dataType:'json',
                success: loadCallback,
                error: loadCallbackE,
                data: { "delete":i,magic_roxen_automatic_charset_variable : 'åäö&#x829f;' }
              });

    }


 }
  return false;
}

function fplloaddata(i) {

  var tmp = YAHOO.lang.JSON.parse(fplloadedfiles[i].data);
  //var tmp = data;
  var _navaids = tmp.navaids;
  var navaids = { };
  var plan = new Array();
  $.each(_navaids,  function() {  
     var na = this;
     navaids[na['hash']] = new Navaid(na['kind'], na['code'],na['name'],na['lat'],na['lng'],na['hash'], na['distance']) ;
   }
  );

  $.each(tmp.plan,  function() {  
     var wp = this;

     var owp = new Waypoint();
     if(wp.navaid) {
	var na =  navaids[wp.navaid];
	if(na.kind == 'usr')
	{
	   owp.navaid = null;
	   wp.lat = na.lat;
	   wp.lng = na.lng;
           wp.description = na.name;
	}
	else
	   owp.navaid = na;
     }
     else
       owp.navaid = null;
     owp.lat = wp.lat;
     owp.lng = wp.lng;
     owp.tas = wp.tas;
     owp.wd = wp.wd;
     owp.ws = wp.ws;
     owp.vari = wp.vari;
     owp.description = wp.description;

      plan.push(owp);
   } );

   


  $('#fuelavg').val(tmp['fuelavg']);
  $('#fuelunit').val(tmp['fuelunit']);

  var usetoc = tmp['usetoc'];
  if(!usetoc) usetoc = '0';

  var fueltoctime = tmp['fueltoctime'];
  if(!fueltoctime) fueltoctime = '0';

  var fueltocdist = tmp['fueltocdist'];
  if(! fueltocdist) fueltocdist = '0';

  var fueltocfuel = tmp['fueltocfuel'];
  if(! fueltocfuel) fueltocfuel = '0';

  var fuelreserve = tmp['fuelreserve'];
  if(! fuelreserve) fuelreserve = '45';

  var fueltaxi = tmp['fueltaxi'];
  if(! fueltaxi) fueltaxi = '0';


  jQuery('#usetoc').val(usetoc);
  jQuery('#fueltoctime').val(fueltoctime);
  jQuery('#fueltocdist').val(fueltocdist);
  jQuery('#fueltocfuel').val(fueltocfuel);
  jQuery('#fuelreserve').val(fuelreserve);
  jQuery('#fueltaxi').val(fueltaxi);


  if(tmp['mapdata'] == 1) {
    fplgmap.setCenter(new GLatLng(tmp['maplat'],  tmp['maplng']), tmp['mapzoom']);

   switch(tmp['maptype']) {
   case "satellite":
     fplgmap.setMapType(G_SATELLITE_MAP);
     break;
   case "hybrid":
     fplgmap.setMapType(G_HYBRID_MAP);
     break;
   case "physical":
     fplgmap.setMapType(G_PHYSICAL_MAP);
    break;
   default:
     fplgmap.setMapType(G_NORMAL_MAP);
   }


   ctrOverlayRemove();
   tmaOverlayRemove();
   restrictedOverlayRemove();

    if(tmp['mapctr'] == 1) {
      $('#ctrcheckbox').attr('checked',true);
      ctrOverlay();
    }
    else
      $('#ctrcheckbox').removeAttr('checked');

    if(tmp['maptma'] == 1) {
      $('#tmacheckbox').attr('checked',true);
      tmaOverlay();
    }
    else
      $('#tmacheckbox').removeAttr('checked');

    if(tmp['mapr'] == 1) {
      $('#restrictedcheckbox').attr('checked',true);
      restrictedOverlay();
    }
    else
      $('#restrictedcheckbox').removeAttr('checked');

   }

  if(tmp['extra'])
	fplExtra = tmp['extra'];
  else
      fplExtra = { };

  fplPlan = plan;
  
  fplSetDirty(0);
  fplSetDocTitle(fplloadedfiles[i].name);

  fplDisplayPlan();
  fplDrawPlan();

  if(tmp['mapdata'] == 1) {
    // set center again to compensate for resize
    fplgmap.setCenter(new GLatLng(tmp['maplat'],  tmp['maplng']), tmp['mapzoom']);
  }

}





function  saveCallbackE(XMLHttpRequest, textStatus, errorThrown) {
  alert('Errorsaving data to the server!');
  fplsavedlg.hide();
}

function saveCallback(json) {

  //FIXME: warn if error

  fplSetDirty(0);
  fplsavedlg.hide();
}

function fplsave() {
  $('#savefiles').html('');
  $('#filename').val(fplDocTitle); 
  fplsavedlg.show();


  $.ajax( {
		url:'loadsave.xml',
		dataType:'json',
                success: saveloadCallback,
                error: saveloadCallbackE,
                data: { magic_roxen_automatic_charset_variable : 'åäö&#x829f;' }
             });

}

function fplselectsavefile(i) {
  $('#filename').val(fplloadedfiles[i].name);
}

function fplClickedSave() {

   var filename = $('input#filename').val();

   if(filename == '') {
     alert('Du måste ange ett filnamn.');
     return;
   }


   for(i=0; i < fplloadedfiles.length; i++) {
     if(fplloadedfiles[i].name == filename)
       if(!confirm('Bekräfta att du vill skriva över sparad fil.'))
         return;
   }
  

  var tmp = { };

  tmp['fuelavg'] = my_parse($('#fuelavg').val()) ;
  tmp['fuelunit'] = $('#fuelunit').val();

  tmp['usetoc'] = jQuery('#usetoc').val();
  tmp['fueltoctime'] = jQuery('#fueltoctime').val();
  tmp['fueltocdist'] = jQuery('#fueltocdist').val();
  tmp['fueltocfuel'] = jQuery('#fueltocfuel').val();
  tmp['fuelreserve'] = jQuery('#fuelreserve').val();
  tmp['fueltaxi'] = jQuery('#fueltaxi').val();

  var _maptype = fplgmap.getCurrentMapType();
  var maptype = "map"; 
  if (_maptype == G_SATELLITE_MAP) {
    maptype = "satellite"; 
  } 
  if (_maptype == G_HYBRID_MAP) { 
    maptype = "hybrid"; 
  }
  if (_maptype == G_PHYSICAL_MAP) { 
    maptype = "physical"; 
  } 

  tmp['maptype'] = maptype;

  var mapcenter =  fplgmap.getCenter();
  tmp['mapdata'] = 1;
  tmp['maplat'] = mapcenter.lat();
  tmp['maplng'] = mapcenter.lng();
  tmp['mapzoom'] = fplgmap.getZoom();

  var mapctr  = $('#ctrcheckbox').attr('checked') ? 1 : 0;
  var maptma  = $('#tmacheckbox').attr('checked') ? 1 : 0;
  var mapr  = $('#restrictedcheckbox').attr('checked') ? 1 : 0;

  tmp['mapctr'] = mapctr;
  tmp['maptma'] = maptma;
  tmp['mapr'] =  mapr;

  var navaids = { };
  var plan = new Array();

   for(i = 0; i < fplPlan.length ; i++) {
     plan.push(fplPlan[i].save());

     if(fplPlan[i].navaid) {
       if(!navaids[fplPlan[i].navaid.hash])  {
           navaids[fplPlan[i].navaid.hash] =  fplPlan[i].navaid.save();
       }
     }
   }

  tmp['navaids'] = navaids;
  tmp['plan'] = plan;

  tmp['extra'] = fplExtra;

  fplSetDocTitle(filename);

  $.ajax( {
		url:'loadsave.xml',
		dataType:'json',
                success: saveCallback,
                error: saveCallbackE,
                data: {'save': YAHOO.lang.JSON.stringify(tmp) ,'name':filename, magic_roxen_automatic_charset_variable : 'åäö&#x829f;' }
             });

}

//
// Fuel dialog
//

function fplfueldlgTaxiChanged() {
  var val = my_parse(jQuery('#_fueltaxi').val(), true);
  jQuery('#_fueltaxi').val( val );
  jQuery('#fueltabletaxi').html( val );
  fplfueldlgSumFuel();
}
function fplfueldlgAvgChanged() {
  jQuery('#_fuelavg').val( my_parse(jQuery('#_fuelavg').val(), true));
  fplfueldlgCalcReserveFuel();
  fplfueldlgCalcTripFuel();
  fplfueldlgSumFuel();
}
function fplfueldlgReserveChanged() {
  jQuery('#_fuelreserve').val( my_parse(jQuery('#_fuelreserve').val(), true));
  fplfueldlgCalcReserveFuel();
  fplfueldlgSumFuel();
}
function fplfueldlgTocFuelChanged() {
  jQuery('#_fueltocfuel').val( my_parse(jQuery('#_fueltocfuel').val(), true));
  fplfueldlgCalcTripFuel();
  fplfueldlgSumFuel();
}
function fplfueldlgTocTimeChanged() {
  jQuery('#_fueltoctime').val( my_parse(jQuery('#_fueltoctime').val(), true));
  fplfueldlgCalcTripFuel();
  fplfueldlgSumFuel();
}
function fplfueldlgTocDistChanged() {
  jQuery('#_fueltocdist').val( my_parse(jQuery('#_fueltocdist').val(), true));
  fplfueldlgCalcTripFuel();
  fplfueldlgSumFuel();
}

function fplfueldlgCalcTripFuel() {
  var val = fplDisplayPlan(true);
   
  jQuery('#fueltabletrip').html(val.toFixed(1))
}
function fplfueldlgCalcReserveFuel() {
  jQuery('#fueltablereserve').html( (my_parse(jQuery('#_fuelavg').val()) * my_parse(jQuery('#_fuelreserve').val()) / 60.0 ).toFixed(1) );
}

function fplfueldlgSumFuel() {
   var val = 
      my_parse(jQuery('#fueltabletaxi').html())+
      my_parse(jQuery('#fueltabletrip').html())+
      my_parse(jQuery('#fueltablereserve').html());
  jQuery('#fueltablesum').html( val.toFixed(1) );
}

function fplfueldlgUnitChanged() {
  jQuery('.fuelunitlegend').html(jQuery('#_fuelunit').val());
}

function fplfueldlgUsetocChanged(quick) {
  var toc =jQuery('#_usetoc').attr('checked');
  if(toc) {
     jQuery('#fuelavglegend').html('Genomsnittlig bränsleförbrukning under cruise:');
     if(quick)
       $('#tocparameters').show();
     else
       $('#tocparameters').slideDown('normal');
  }
  else {
   jQuery('#fuelavglegend').html('Genomsnittlig bränsleförbrukning:');
   if(quick)
     $('#tocparameters').hide();
   else
     $('#tocparameters').slideUp('normal');
 }
  fplfueldlgCalcTripFuel();
  fplfueldlgSumFuel();
}

function fplfueldlgDone() {
  var changed = false;

  if(jQuery('#fuelunit').val() != jQuery('#_fuelunit').val() ||
     jQuery('#fuelavg').val()  != jQuery('#_fuelavg').val() ||
     jQuery('#usetoc').val() != (jQuery('#_usetoc').attr('checked') ? '1' : '0' ) ||
     jQuery('#fueltoctime').val() != jQuery('#_fueltoctime').val() ||
     jQuery('#fueltocdist').val() != jQuery('#_fueltocdist').val() ||
     jQuery('#fueltocfuel').val() != jQuery('#_fueltocfuel').val() ||
     jQuery('#fuelreserve').val() != jQuery('#_fuelreserve').val() ||
     jQuery('#fueltaxi').val() != jQuery('#_fueltaxi').val()) {

   changed = true;
   fplSetDirty(1);
  }

  jQuery('#fuelunit').val(jQuery('#_fuelunit').val());
  jQuery('#fuelavg').val(jQuery('#_fuelavg').val());
  jQuery('#usetoc').val(jQuery('#_usetoc').attr('checked') ? '1' : '0' );
  jQuery('#fueltoctime').val(jQuery('#_fueltoctime').val());
  jQuery('#fueltocdist').val(jQuery('#_fueltocdist').val());
  jQuery('#fueltocfuel').val(jQuery('#_fueltocfuel').val());
  jQuery('#fuelreserve').val(jQuery('#_fuelreserve').val());
  jQuery('#fueltaxi').val(jQuery('#_fueltaxi').val());

  if(changed) {
    fplDisplayPlan();
    fplDrawPlan(); //FIXME: only if we're going to draw TOC marker
  }
  fplfueldlg.hide()
}

function fplfueldlgCancel() {
  fplfueldlg.hide();
}

function fplfueldlgShow() {
  jQuery('#_fuelunit').val(jQuery('#fuelunit').val());
  jQuery('#_fuelavg').val(jQuery('#fuelavg').val());
  jQuery('#_usetoc').attr('checked', jQuery('#usetoc').val() == '1');
  jQuery('#_fueltoctime').val(jQuery('#fueltoctime').val());
  jQuery('#_fueltocdist').val(jQuery('#fueltocdist').val());
  jQuery('#_fueltocfuel').val(jQuery('#fueltocfuel').val());
  jQuery('#_fuelreserve').val(jQuery('#fuelreserve').val());
  jQuery('#_fueltaxi').val(jQuery('#fueltaxi').val());

  fplfueldlgUnitChanged();
  fplfueldlgUsetocChanged(true);
  //FIXME: waste of cpu here
  fplfueldlgTaxiChanged();
  fplfueldlgAvgChanged();
  fplfueldlgReserveChanged();
  fplfueldlgTocFuelChanged();
  fplfueldlgTocDistChanged();
  fplfueldlgTocTimeChanged();

  fplfueldlg.show();
}

// END Fuel dialog


function fplinit() {
  YAHOO.util.Event.on(window, 'resize', resizeFplApp, this, true);

  window.onbeforeunload = function() { 
    if(fplisdirty == 1) {
        return 'Varning! Om du lämnar sidan så förlorar du din färdplan.';
    }
  };
 
  //FIXME: .attr
  $('#leglength').val('30');
  $('#searchText').val('');
  $('#splitlegwind').get(0).checked = false;

  $('#ctrcheckbox').get(0).checked = false;
  $('#tmacheckbox').get(0).checked = false;
  $('#restrictedcheckbox').get(0).checked = false;

  jQuery('#fuelunit').val('l');
  jQuery('#fuelavg').val('40');
  jQuery('#usetoc').val( '0' );
  jQuery('#fueltoctime').val('0');
  jQuery('#fueltocdist').val('0');
  jQuery('#fueltocfuel').val('0');
  jQuery('#fueltaxi').val('0');
  jQuery('#fuelreserve').val('45');


  resizeFplApp()
  ShowGMap();

   var icon;

  //FIXME code dup
   icon  = new GIcon();
   icon.image = "gfx/marker_toc.png";
   icon.iconSize = new GSize(21, 31);
   icon.shadow = "gfx/marker_shadow.png";
   icon.shadowSize = new GSize(52, 29);
   icon.iconAnchor = new GPoint(7, 31);
   icon.infoWindowAnchor = new GPoint(5, 2);
   fplgicons['toc'] = icon;

   icon  = new GIcon();
   icon.image = "gfx/marker_gps.png";
   icon.iconSize = new GSize(21, 31);
   icon.shadow = "gfx/marker_shadow.png";
   icon.shadowSize = new GSize(52, 29);
   icon.iconAnchor = new GPoint(7, 31);
   icon.infoWindowAnchor = new GPoint(5, 2);
   fplgicons['gps'] = icon;

   icon  = new GIcon();
   icon.image = "gfx/marker_apt.png";
   icon.iconSize = new GSize(21, 31);
   icon.shadow = "gfx/marker_shadow.png";
   icon.shadowSize = new GSize(52, 29);
   icon.iconAnchor = new GPoint(7, 31);
   icon.infoWindowAnchor = new GPoint(5, 2);
   fplgicons['apt'] = icon;

   icon  = new GIcon();
   icon.image = "gfx/marker_vor.png";
   icon.iconSize = new GSize(21, 31);
   icon.shadow = "gfx/marker_shadow.png";
   icon.shadowSize = new GSize(52, 29);
   icon.iconAnchor = new GPoint(7, 31);
   icon.infoWindowAnchor = new GPoint(5, 2);
   fplgicons['vor'] = icon;

   icon  = new GIcon();
   icon.image = "gfx/marker.png";
   icon.iconSize = new GSize(21, 31);
   icon.shadow = "gfx/marker_shadow.png";
   icon.shadowSize = new GSize(52, 29);
   icon.iconAnchor = new GPoint(7, 31);
   icon.infoWindowAnchor = new GPoint(5, 2);
   fplgicons['vordme'] = icon;

   icon  = new GIcon();
   icon.image = "gfx/marker_ndb.png";
   icon.iconSize = new GSize(21, 31);
   icon.shadow = "gfx/marker_shadow.png";
   icon.shadowSize = new GSize(52, 29);
   icon.iconAnchor = new GPoint(7, 31);
   icon.infoWindowAnchor = new GPoint(5, 2);
   fplgicons['ndb'] = icon;

   icon  = new GIcon();
   icon.image = "gfx/marker_intersection.png";
   icon.iconSize = new GSize(21, 31);
   icon.shadow = "gfx/marker_shadow.png";
   icon.shadowSize = new GSize(52, 29);
   icon.iconAnchor = new GPoint(7, 31);
   icon.infoWindowAnchor = new GPoint(5, 2);
   fplgicons['intersection'] = icon;

   icon  = new GIcon();
   icon.image = "gfx/marker.png";
   icon.iconSize = new GSize(21, 31);
   icon.shadow = "gfx/marker_shadow.png";
   icon.shadowSize = new GSize(52, 29);
   icon.iconAnchor = new GPoint(7, 31);
   icon.infoWindowAnchor = new GPoint(5, 2);
   fplgicons['dme'] = icon;




   fpldisclaimerdlg = new YAHOO.widget.Panel("fpldisclaimer",  
            { width : "650px", 
               close:false,  
	    visible:false,  
	    draggable:false,
              fixedcenter : true, 
	      modal: true          
	             } ); 
        fpldisclaimerdlg.render();
       YAHOO.util.Event.addListener("fpldisclaimerok", "click", closedDisclaimer, fpldisclaimerdlg , true);


   fplhelpdlg = new YAHOO.widget.Panel("fplhelp",  
            { width : "650px", 
               close:false,  
	    visible:false,  
	    draggable:true,
              fixedcenter : true, 
	      modal: true          
	             } ); 
        fplhelpdlg.render();
        YAHOO.util.Event.addListener("fplhelpok", "click", fplhelpdlg.hide, fplhelpdlg , true);



   fpleditlegdlg = new YAHOO.widget.Panel("fpleditleg",  
            { width : "650px", 
              xy : [ 200,200 ],
               close:true,  
	    visible:false,  
	    draggable:true,
              fixedcenter : false, 
	      modal: true,
              constraintoviewport:true
	             } ); 
        fpleditlegdlg.render();
 
  fplloaddlg = new YAHOO.widget.Panel("fplload",  
            { width : "650px", 
              xy : [ 200,200 ],
               close:true,  
	    visible:false,  
	    draggable:true,
              fixedcenter : false, 
	      modal: true,
              constraintoviewport:true
	             } ); 
        fplloaddlg.render();

  fplsavedlg = new YAHOO.widget.Panel("fplsave",  
            { width : "650px", 
              xy : [ 200,200 ],
               close:true,  
	    visible:false,  
	    draggable:true,
              fixedcenter : false, 
	      modal: true,
              constraintoviewport:true
	             } ); 
        fplsavedlg.render();

  fpllogindlg = new YAHOO.widget.Panel("fpllogin",  
            {  
              xy : [ 200,200 ],
               close:true,  
	    visible:false,  
	    draggable:true,
              fixedcenter : false, 
	      modal: true,
              constraintoviewport:true
	             } ); 
        fpllogindlg.render();

  fplsharedlg = new YAHOO.widget.Panel("fplshare",  
            { width : "650px", 
              xy : [ 200,200 ],
               close:true,  
	    visible:false,  
	    draggable:true,
              fixedcenter : false, 
	      modal: true,
              constraintoviewport:true
	             } ); 
        fplsharedlg.render();

   fplsplitlegdlg = new YAHOO.widget.Panel("fplsplitleg",  
            { width : "650px", 
              xy : [ 200,200 ],
               close:true,  
	    visible:false,  
	    draggable:true,
              fixedcenter : false, 
	      modal: true,
              constraintoviewport:true
	             } ); 
        fplsplitlegdlg.render();

   fplfueldlg = new YAHOO.widget.Panel("fplfuel",  
            { width : "600px", 
              xy : [ 200,200 ],
               close:true,  
	    visible:false,  
	    draggable:true,
              fixedcenter : false, 
	      modal: true,
              constraintoviewport:true
	             } ); 
        fplfueldlg.render();

  fplSetDirty(0);

  if(is_ie()) {
     // stupid IE
     fplfueldlg.show();
     fplfueldlg.hide();
   }

   if(!YAHOO.util.Cookie.get('fplv200hidedisclaimer'))
      fpldisclaimerdlg.show();
   else
     fplinit2();
}

function closedDisclaimer() {
  fpldisclaimerdlg.hide();
  if($('#fplhidedisclaimer').attr('checked')) {

     var expDate=new Date();
     expDate.setDate(expDate.getDate()+365);
     YAHOO.util.Cookie.set('fplv200hidedisclaimer','1', { 'path':'/', expires:expDate } );
  }

  fplinit2();
}

function fplinit2() {
  if(bootstrapload)
    fplloadotherplan(bootstrapload);
}


function ShowGMap() {
  if(GBrowserIsCompatible()) {    
    map = new GMap(document.getElementById("googlemap"));
    map.addMapType(G_PHYSICAL_MAP);
    //map.setMapType(G_PHYSICAL_MAP);
    //map.setMapType(G_MAP_TYPE);
    map.enableContinuousZoom();
    map.enableScrollWheelZoom();
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());

    var omap = new GOverviewMapControl();
    map.addControl(omap);
    omap.hide(true); // Kludge to prevent bug when resizing
    omap.show(true); // ...

    map.centerAndZoom(new GPoint(15.8, 58.5), 10);

    GEvent.addListener(map, "click", function(marker, point, markerpoint) {
      if (marker) {
        if(marker.getTitle) 
           return false;
        if(markerpoint.lat != null) {
          fplMapClick(markerpoint.lat(),markerpoint.lng());
        }
      } else {
        fplMapClick(point.lat(),point.lng());
      }
});
    fplgmap = map;
  }
}

function formatTime(secs) {
  var hours = Math.floor(secs/(60*60));
  var mins = (secs - (hours*60*60)) / 60.0;
  var minsS = mins.toFixed(0).toString();
  if(minsS=="60") { minsS="00"; hours+=1; }
  return hours.toString() + ':' + (minsS.length<2?'0':'') + minsS;
}

function formatMins(mins) {
  var res = mins.toFixed(1).toString();
  if(res.length <4)
     res = '0'+res;
  return res;
}

function formatMinsAts(mins) {
  var res = mins.toFixed(0).toString();
  if(res.length <2)
     res = '0'+res;
  return res;
}

function format_coord(lat, lng) {
  var res='';
  if(lat >= 0.0)
    res = res + 'N';
  else {
    res = res + 'S';
    lat = -lat;
  }
  latDeg = Math.floor(lat);
  latMin = formatMins((lat - latDeg)*60);
  if(latMin == '60.0') {
    latDeg = latDeg+1;
    latMin = '00.0';
  }
  if(latDeg < 10)
    res = res + '0';
  res = res + latDeg.toString() + '°';
  res = res + latMin + "'";

  res = res + ' ';

  if(lng >= 0.0)
    res = res + 'E';
  else {
    res = res + 'W';
    lng = -lng;
  }
  lngDeg = Math.floor(lng);
  lngMin = formatMins((lng - lngDeg)*60);
  if(lngMin == '60.0') {
    lngDeg = lngDeg+1;
    lngMin = '00.0';
  }
  if(lngDeg < 10)
    res = res + '00';
  else if(lngDeg < 100)
    res = res + '0';
  res = res + lngDeg.toString() + '°';
  res = res + lngMin + "'";

  return res;
}

function format_coord_ats(lat, lng) {
  var res='';
  var ns = '';
  var ew = '';

  if(lat >= 0.0)
    ns = 'N';
  else {
    ns = 'S';
    lat = -lat;
  }
  latDeg = Math.floor(lat);
  latMin = formatMinsAts((lat - latDeg)*60);
  if(latMin == '60') {
    latDeg = latDeg+1;
    latMin = '00';
  }
  if(latDeg < 10)
    res = res + '0';
  res = res + latDeg.toString();
  res = res + latMin ;

  res = res + ns;

  if(lng >= 0.0)
    ew = 'E';
  else {
    ew = 'W';
    lng = -lng;
  }
  lngDeg = Math.floor(lng);
  lngMin = formatMinsAts((lng - lngDeg)*60);
  if(lngMin == '60') {
    lngDeg = lngDeg+1;
    lngMin = '00';
  }
  if(lngDeg < 10)
    res = res + '00';
  else if(lngDeg < 100)
    res = res + '0';
  res = res + lngDeg.toString() ;
  res = res + lngMin + ew;

  return res;
}

function calc_dist_track(lat1,lng1,lat2,lng2) {

  var PI = 3.141592654;

  if(lat1==lat2 && lng1==lng2)
    return [ 0.0, 0.0 ];

  // radians...
  lat1 *= ( 2*PI / 360);
  lng1 *= ( 2*PI / 360);
  lat2 *= ( 2*PI / 360);
  lng2 *= ( 2*PI / 360);

  var d =
    2*Math.asin(Math.sqrt(Math.pow((Math.sin((lat1-lat2)/2)),2) +
                Math.cos(lat1)*Math.cos(lat2)*Math.pow((Math.sin((lng1-lng2)/2)),2)));

  var track;

  if(Math.sin(lng1-lng2) < 0.0)
    track=Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d))/(Math.sin(d)*Math.cos(lat1)));
  else
    track=2*PI-Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d))/(Math.sin(d)*Math.cos(lat1)));

  return [ ((180*60)/PI)*d, track*(180.0/PI) ];
}

function calc_xtd_atd(lat1,lng1,lat2,lng2, alat, alng) {
  var PI = 3.141592654;
  var AB = calc_dist_track(lat1,lng1,lat2,lng2);
  var AD = calc_dist_track(lat1,lng1,alat,alng);
  var dist_AD = AD[0] / ((180*60)/PI);
  var dist_AB = AB[0] / ((180*60)/PI);
  var crs_AB = AB[1] / (180.0/PI);
  var crs_AD = AD[1] / (180.0/PI);
  var xtd =  Math.asin(Math.sin(dist_AD)*Math.sin(crs_AD-crs_AB));
  var atd = Math.acos(Math.cos(dist_AD)/Math.cos(xtd));
  var crsdiff = ((crs_AD - crs_AB) + (2*PI)) % (2*PI);
  if( crsdiff > (PI/2) && crsdiff < (3*PI/2))
    atd = -atd;
  return [xtd*((180*60)/PI), atd*((180*60)/PI), atd/dist_AB, dist_AB*((180*60)/PI)];
}

function calc_intermediate_point(lat1,lon1,lat2,lon2,frac,dist) {
  var PI = 3.141592654;
  var lat2, lng2;

  // radians...
  lat1 *= ( 2*PI / 360);
  lon1 *= -( 2*PI / 360);
  lat2 *= ( 2*PI / 360);
  lon2 *= -( 2*PI / 360);
  dist = (PI/(180*60))*dist;

  var A = Math.sin((1-frac)*dist)/Math.sin(dist);
  var B = Math.sin(frac*dist)/Math.sin(dist);
  var x = A*Math.cos(lat1)*Math.cos(lon1) + B*Math.cos(lat2)*Math.cos(lon2);
  var y = A*Math.cos(lat1)*Math.sin(lon1) + B*Math.cos(lat2)*Math.sin(lon2);
  var z = A*Math.sin(lat1) + B*Math.sin(lat2);
  var lat=Math.atan2(z,Math.sqrt(x*x+y*y));
  var lon=Math.atan2(y,x);

  return [ lat*(180.0/PI), -lon*(180.0/PI)];

}

function calc_radial_dist(lat1,lng1,radial,dist) {
  var PI = 3.141592654;
  var lat2, lng2;

  // radians...
  lat1 *= ( 2*PI / 360);
  lng1 *= -( 2*PI / 360);
  radial *= ( 2*PI / 360);
  dist = (PI/(180*60))*dist;

  lat2 = Math.asin(Math.sin(lat1)*Math.cos(dist)+Math.cos(lat1)*Math.sin(dist)*Math.cos(radial));
  if(Math.abs(Math.cos(lat2))<0.00001)
    lng2=lng1;
  else
    lng2= (
	     (  
                  (lng1-Math.asin(Math.sin(radial)*Math.sin(dist)/Math.cos(lat2))+PI) 
                 % (2*PI))
           ) - PI;

  return [ lat2*(180.0/PI), -lng2*(180.0/PI)];
}

function calc_wind(tas,wd2,ws,tt2,dist) {
  var PI = 3.141592654;
  // radians
  var wd = (wd2 / 360) * 2 * PI;
  var tt = (tt2 / 360) * 2 * PI;

  //FIXME: handle too strong wind
  var swc = (ws/tas)*Math.sin(wd-tt);
  var th = tt + Math.asin(swc);

  if(th < 0.0)
    th += (2*PI);
  if(th>(2*PI))
    th -= (2*PI);

   var gs = tas*Math.sqrt(1-swc*swc)-ws*Math.cos(wd-tt);
   var wca =  th - tt;

   t = (dist / gs) * 60 * 60;
  
  return [ gs, t, th/(2*PI)*360.0, wca/(2*PI)*360.0 ];
}


//
// class Navaid
// 


function Navaid(kind,code,name,lat,lng,hash,distance) {
  this.kind = kind;
  this.code = code;
  this.name = name;
  this.lat = lat;
  this.lng = lng;
  this.hash = hash;
  this.distance = distance;

  //fns
  this.srHtml = srHtml;
  this.srangeHtml = srangeHtml;
  this.save = save;

  function save() {
    var tmp = { };
    tmp['kind'] =  this.kind;
    tmp['code'] =  this.code;
    tmp['name'] =  this.name;
    tmp['lat'] =  this.lat;
    tmp['lng'] =  this.lng;
    tmp['hash'] =  this.hash;
    tmp['distance'] =   this.distance;

   return tmp;
  }

  function kindHtml(kind) {
    var kind2 = null;
   
    switch(kind) {
      case 'ndb':
      case 'apt':
      case 'vor':
        kind2 = kind;
        break;
      case 'fix':
        kind2 = 'intersection';
        break;
    }

    if(kind2 != null)
     return '<img src="gfx/'+kind2+'.gif"/>';
    else
     return '';
  }

  function srHtml() {
    var srHtml = '<a class="blocklink" href="#" onClick="fplAddNavaidToPlan(\''+this.hash+'\');return false;">';
    srHtml += '<table><tr><td rowspan="2">';
    srHtml += kindHtml(this.kind);
    srHtml += '</td></tr><tr><td>';
    srHtml += this.name+' ('+this.code+')';
    srHtml += '<br/><span class="mini"> '+this.distance.toFixed(1).toString() +' nm från ESSL</span>';
    srHtml += '</td></tr></table>';
    srHtml += '</a> ';
    return srHtml;
  }

  function oldsrHtml() {
    var srHtml = '<a onClick="fplShowTmpMarker(\''+this.name+'\',\''+this.code+'\','+this.lat+','+this.lng+');return false;">';
    srHtml += kindHtml(this.kind);
    srHtml += this.kind + '*';
    srHtml += this.name+' ('+this.code+')';
    srHtml += '</a> ';
    srHtml = srHtml + '<a onClick="fplAddNavaidToPlan(\''+this.hash+'\');return false;">[+]</a>';
    srHtml = srHtml + '<br/>';
    return srHtml;
  }

  function srangeHtml(idx) {
    var srHtml = '';
    srHtml = srHtml + '<a class="blocklink"  href="#" onClick="fplReplaceWithNavaid('+idx+',\''+this.hash+'\');fpleditlegdlg.hide();return false;">';
    srHtml += '<table><tr><td rowspan="2">';
    srHtml += kindHtml(this.kind);
    srHtml += '</td></tr><tr><td>';
    srHtml += this.name+' ('+this.code+')';
    srHtml += '<br/><span class="mini"> '+this.distance.toFixed(1).toString() +' nm från nuvarande</span>';
    srHtml += '</td></tr></table>';
    srHtml = srHtml + '</a>';
    return srHtml;
  }

}

//
// class Waypoint
//

function Waypoint() {
  this.navaid = null;
  this.lat = 0.0;
  this.lng = 0.0;

  this.tas = 100;
  this.wd = 0;
  this.ws = 0;
  this.vari = 0;
  this.description = '';

  this.copyLegConf = copyLegConf;
  this.setNavaid = setNavaid;
  this.setLatLong = setLatLong;
  this.getLat = getLat;
  this.getLong = getLong;
  this.describe = describe;
  this.atsdescribe = atsdescribe;
  this.save = save;
  this.icontype = icontype;

  function save() {
    var tmp = { };
    if(this.navaid)
       tmp['navaid'] = this.navaid.hash;
    else
       tmp['navaid'] =  null;
   
    tmp['lat'] =  this.lat;
    tmp['lng'] =  this.lng;
    tmp['tas'] =  this.tas;
    tmp['wd'] =  this.wd;
    tmp['ws'] =  this.ws;
    tmp['vari'] =  this.vari;
    tmp['description'] =  this.description;

    return tmp;
  }

   function copyLegConf(wp) {
     this.tas = wp.tas;
     this.wd = wp.wd;
     this.ws = wp.ws;
     this.vari = wp.vari;
   }


   function icontype() {
     if(!this.navaid)
       return 'gps';
     switch(this.navaid.kind) {
       case 'fix':
          return 'intersection';
           break;
       default:
          return this.navaid.kind;
     }
   }

   function describe(i) {
    var html = '';
    if(this.navaid) {
      if(i != 0)
         html = html + (i).toString() + ': ';
      if(this.navaid.kind == 'fix')
        html = html +this.navaid.name;
      else
        html = html +this.navaid.name+' ('+this.navaid.code+')';
    } else {
      if(i != 0)
        html = (i).toString() + ': ';

      if(this.description  && this.description != '')
        html = html + this.description + ' (' + format_coord(this.lat, this.lng) + ')';
      else
        html = html + 'Koordinat: ' + format_coord(this.lat, this.lng);
      //html = html + ' ' + this.lat;
      //html = html + ' ' + this.lng;
    }
    return html;
   }

   function atsdescribe() {
    var txt = '';
    if(this.navaid && this.navaid.kind != 'apt') {
       txt += this.navaid.code;
    } else {
      txt += format_coord_ats(this.getLat(), this.getLong());
    }
    return txt;
   }

   function setNavaid(na) {
     this.navaid = na;
     this.description = '';
     return;
   }

   function setLatLong(lat1,lng1) {
    this.navaid = null;
    this.lat = lat1;
    this.lng = lng1;
    return;
   }

   function getLat() {
     if(this.navaid)
       return this.navaid.lat;
     return this.lat;
   }

   function getLong() {
     if(this.navaid)
       return this.navaid.lng;
    return this.lng;
   }

}






//////////////////////////////////////////////////////////////////////////////
// custom drag and drop implementation
//////////////////////////////////////////////////////////////////////////////

DDList = function(id, sGroup, config) {

    DDList.superclass.constructor.call(this, id, sGroup, config);

    this.logger = this.logger || YAHOO;
    var el = this.getDragEl();
    YAHOO.util.Dom.setStyle(el, "opacity", 0.67); // The proxy is slightly transparent

    this.goingUp = false;
    this.lastY = 0;

   this.endDragEvent = new YAHOO.util.CustomEvent ( "endDrag" , this );
};

YAHOO.extend(DDList, YAHOO.util.DDProxy, {

    startDrag: function(x, y) {

     jQuery('li.toc').hide();

        // make the proxy look like the source element
        var dragEl = this.getDragEl();
        var clickEl = this.getEl();
        YAHOO.util.Dom.setStyle(clickEl, "visibility", "hidden");

        dragEl.innerHTML = clickEl.innerHTML;

        YAHOO.util.Dom.setStyle(dragEl, "color", YAHOO.util.Dom.getStyle(clickEl, "color"));
        YAHOO.util.Dom.setStyle(dragEl, "backgroundColor", YAHOO.util.Dom.getStyle(clickEl, "backgroundColor"));
        YAHOO.util.Dom.setStyle(dragEl, "border", "2px solid gray");
        YAHOO.util.Dom.setStyle(dragEl, "text-align", "left");
    },

    endDrag: function(e) {

        var srcEl = this.getEl();
        var proxy = this.getDragEl();

        // Show the proxy element and animate it to the src element's location
        YAHOO.util.Dom.setStyle(proxy, "visibility", "");
        var a = new YAHOO.util.Motion( 
            proxy, { 
                points: { 
                    to: YAHOO.util.Dom.getXY(srcEl)
                }
            }, 
            0.2, 
            YAHOO.util.Easing.easeOut 
        )
        var proxyid = proxy.id;
        var thisid = this.id;

        // Hide the proxy and show the source element when finished with the animation
        a.onComplete.subscribe(function() {
                YAHOO.util.Dom.setStyle(proxyid, "visibility", "hidden");
                YAHOO.util.Dom.setStyle(thisid, "visibility", "");
            });
        a.animate();
        this.endDragEvent.fire();
    },

    onDragDrop: function(e, id) {

        // If there is one drop interaction, the li was dropped either on the list,
        // or it was dropped on the current location of the source element.
        if (YAHOO.util.DragDropMgr.interactionInfo.drop.length === 1) {

            // The position of the cursor at the time of the drop (YAHOO.util.Point)
            var pt = YAHOO.util.DragDropMgr.interactionInfo.point; 

            // The region occupied by the source element at the time of the drop
            var region = YAHOO.util.DragDropMgr.interactionInfo.sourceRegion; 

            // Check to see if we are over the source element's location.  We will
            // append to the bottom of the list once we are sure it was a drop in
            // the negative space (the area of the list without any list items)
            if (!region.intersect(pt)) {
                var destEl = YAHOO.util.Dom.get(id);
                var destDD = YAHOO.util.DragDropMgr.getDDById(id);
                destEl.appendChild(this.getEl());
                destDD.isEmpty = false;
                YAHOO.util.DragDropMgr.refreshCache();
            }

        }
    },

    onDrag: function(e) {

        // Keep track of the direction of the drag for use during onDragOver
        var y = YAHOO.util.Event.getPageY(e);

        if (y < this.lastY) {
            this.goingUp = true;
        } else if (y > this.lastY) {
            this.goingUp = false;
        }

        this.lastY = y;
    },

    onDragOver: function(e, id) {
   
        var srcEl = this.getEl();
        var destEl = YAHOO.util.Dom.get(id);

        // We are only concerned with list items, we ignore the dragover
        // notifications for the list.
        if (destEl.nodeName.toLowerCase() == "li") {
            var orig_p = srcEl.parentNode;
            var p = destEl.parentNode;

            if (this.goingUp) {
                p.insertBefore(srcEl, destEl); // insert above
            } else {
                p.insertBefore(srcEl, destEl.nextSibling); // insert below
            }

            YAHOO.util.DragDropMgr.refreshCache();
        }
    }
});
