﻿// JScript File

function GetHoursMinutes(min) {
    var hours = Math.floor(min / 60);
    var mins = min % 60;
    mins = mins.toFixed(0);
    if(mins < 10) mins = "0" + mins;
    var hm = hours.toFixed(0) + ":" + mins;
    return hm;
}

function GetDistance(point1, point2) {
    var x1 = Math.PI * point1.lng() / 180.0;
    var y1 = Math.PI * point1.lat() / 180.0;
    var x2 = Math.PI * point2.lng() / 180.0;
    var y2 = Math.PI * point2.lat() / 180.0;
    var distance = 20000.0 / Math.PI * Math.acos(Math.sin(y1) * Math.sin(y2) + Math.cos(y1) * Math.cos(y2) * Math.cos(x1 - x2));
    return distance;
}

function GetHeading(point1, point2) {
    var d = GetDistance(point1,point2) * Math.PI / 20000.0;
    var x1 = -1 * Math.PI * point1.lng() / 180.0;
    var y1 = Math.PI * point1.lat() / 180.0;
    var x2 = -1 * Math.PI * point2.lng() / 180.0;
    var y2 = Math.PI * point2.lat() / 180.0;

    var heading = Math.acos((Math.sin(y2) - Math.sin(y1) * Math.cos(d)) / (Math.sin(d) * Math.cos(y1)));
    if (Math.sin(x2 - x1) < 0)
    {
        heading = 180.0 * heading / Math.PI;
    }
    else
    {
        heading = 180.0 * (2 * Math.PI - heading) / Math.PI;
    }
    return heading;
}

function leg() {
    this.name;
    this.prevLeg;
    this.srcPoint;
    this.dstPoint;
    this.distance=0;
    this.heading=0;
    this.ete=0;
    this.consumption=0;
    this.nextLeg;
    this.compute=function(velmed, consmed) {
        this.distance=GetDistance(this.srcPoint,this.dstPoint);
        this.heading=GetHeading(this.srcPoint,this.dstPoint);
        this.ete=60.0*this.distance/velmed;
        this.consumption=consmed*this.distance/velmed;
    }
}

function QWaypoint(latlng, lname, icon) {
    this.marker = new GMarker(latlng,icon);
    this.point = latlng;
    this.name;
    if(lname!=null) this.name=lname;
    else this.name="Lat: "+this.point.lat().toFixed(6)+"<br>"+"Lng: "+this.point.lng().toFixed(6);
    this.marker.bindInfoWindowHtml(this.name);
}

function QRouteTable(ltable) {
    
    this.table = ltable;
    
    // style
    this.table.cellPadding="3";
    this.table.cellSpacing="0";
    this.table.border="1";
    this.table.borderStyle="solid";
    this.table.borderColor="black";
            
    this.Update = function(waypoints, legs)  {
        
        while(this.table.lastChild!=null) this.table.removeChild(this.table.lastChild);
        
        // header
        var head = this.table.insertRow(-1);
        head.style.backgroundColor="black";
        head.style.color="white";
        head.style.fontSize="larger";
        head.style.fontWeight="bold";
        var cell = head.insertCell(-1);
        cell.innerHTML = "Waypoint";
        cell = head.insertCell(-1);
        cell.innerHTML = "Rumbo (º)";
        cell = head.insertCell(-1);
        cell.innerHTML = "Distancia (km)";
        cell = head.insertCell(-1);
        cell.innerHTML = "Tiempo (h:m)";
        cell = head.insertCell(-1);
        cell.innerHTML = "Consumo (l)";
       
        // totales
        var totDistance=0;
        var totConsumption=0;
        var totETE=0;
        
        for(w=0; w<waypoints.length; w++) {
        
            // WAYPOINT
            var row = this.table.insertRow(-1);
            var cell = row.insertCell(-1);
            cell.innerHTML = "Waypoint " + w;
            cell = row.insertCell(-1);
            cell.innerHTML = waypoints[w].name;
            cell.style.fontSize="smaller";
            cell = row.insertCell(-1);
            cell.innerHTML = totDistance.toFixed(0);
            cell = row.insertCell(-1);
            cell.innerHTML = GetHoursMinutes(totETE);//totETE.toFixed(0);
            cell = row.insertCell(-1);
            cell.innerHTML = totConsumption.toFixed(1);
                       
            // LEGS
            if(w<legs.length) {
                row = this.table.insertRow(-1);
                row.style.backgroundColor="black";
                row.style.color="white";
                row.style.fontWeight="bold";
                //row.style.fontSize="larger";
                
                cell = row.insertCell(-1);
                cell.innerHTML = "Leg " + w + "-" + (w+1);
                cell = row.insertCell(-1);
                cell.innerHTML = legs[w].heading.toFixed(0);
                cell = row.insertCell(-1);
                cell.innerHTML = legs[w].distance.toFixed(0);
                totDistance+=legs[w].distance;;
                cell = row.insertCell(-1);
                cell.innerHTML = GetHoursMinutes(legs[w].ete.toFixed(0));
                totETE+=legs[w].ete;
                cell = row.insertCell(-1);
                cell.innerHTML = legs[w].consumption.toFixed(1);
                totConsumption+=legs[w].consumption;
            }
        }
    }
}

function QFlightRoute(div,center,zoom,table) {
    // waypoint icon
    this.icon = new GIcon(G_DEFAULT_ICON);
    this.icon.image=this.icon.printImage=this.icon.dragCrossImage="http://maps.google.com/mapfiles/ms/micons/blue-dot.png";
    this.icon.shadow=this.icon.printShadow="http://maps.google.com/mapfiles/ms/micons/msmarker.shadow.png";
    this.icon.iconSize=this.icon.shadowSize=this.icon.dragCrossSize=new GSize(30,30);
    this.icon.iconAnchor=new GPoint(15,30);
    this.icon.infoWindowAnchor=new GPoint(15,0);
    this.icon.dragCrossAnchor=new GPoint(0,-15);
    
    // plane icon
    this.iconPlane = new GIcon(G_DEFAULT_ICON);
    this.iconPlane.image=this.iconPlane.printImage=this.iconPlane.dragCrossImage="http://maps.google.com/mapfiles/ms/micons/plane.png";
    this.iconPlane.shadow=this.iconPlane.printShadow="http://maps.google.com/mapfiles/ms/micons/plane.shadow.png";
    this.iconPlane.iconSize=this.iconPlane.shadowSize=this.iconPlane.dragCrossSize=new GSize(30,30);
    this.iconPlane.iconAnchor=new GPoint(15,15);
    this.iconPlane.infoWindowAnchor=new GPoint(15,15);
    this.iconPlane.dragCrossAnchor=new GPoint(0,0);
    
    // point icon
    this.iconPoint = new GIcon(G_DEFAULT_ICON);
    this.iconPoint.image=this.iconPoint.printImage=this.iconPoint.dragCrossImage="http://maps.google.com/mapfiles/kml/pal4/icon57.png";
    this.iconPoint.shadow=this.iconPoint.printShadow="";
    this.iconPoint.iconSize=this.iconPoint.shadowSize=this.iconPoint.dragCrossSize=new GSize(30,30);
    this.iconPoint.iconAnchor=new GPoint(15,15);
    this.iconPoint.infoWindowAnchor=new GPoint(15,15);
    this.iconPoint.dragCrossAnchor=new GPoint(0,0);

    // member variables
    this.waypoints = new Array();
    this.legs = new Array();
    this.polyline = new GPolyline(this.waypoints.point);
    this.table = new QRouteTable(table);
    
    // init map
    this.qmap = new GMap2(div);
    this.qmap.setCenter(center,zoom);
    this.qmap.addControl(new GLargeMapControl());
    this.qmap.addControl(new GMapTypeControl());
    this.qmap.addMapType(G_PHYSICAL_MAP);
    
    // test
    /*this.geo = new GGeoXml("http://www.diariodevuelo.com/airfields.kml");
    this.qmap.addOverlay(this.geo);*/
    
    // update methods
    this.UpdatePolyline = function() {
        GEvent.clearInstanceListeners(this.polyline);
        this.qmap.removeOverlay(this.polyline);
        for(m in this.waypoints) {
            //GEvent.clearInstanceListeners(this.waypoints[m].marker);
            this.qmap.removeOverlay(this.waypoints[m].marker);
        }
        
        var pts = new Array();
        for(w in this.waypoints) pts.push(this.waypoints[w].point);
        this.polyline = new GPolyline(pts);
        this.qmap.addOverlay(this.polyline);
        for(m in this.waypoints) this.qmap.addOverlay(this.waypoints[m].marker);
    }
    
    this.UpdateFlightRoute = function() {
        this.UpdatePolyline();
        this.table.Update(this.waypoints,this.legs);
    }
    
    // define listeners
    this.OnMapClick = function(overlay, point) {
        if(point!=null) {
            this.OnAddWaypointByCoordinatesClick(point);
        }
        else if(overlay!=null) {
            this.OnAddWaypointByAirfield(overlay);
        }
    }
    
    this.OnMapRightClick = function(point, src, overlay) {
        if(overlay!=null) {
            for(w=0; w<this.waypoints.length; w++) {
                if(overlay==this.waypoints[w].marker) {
                    // rebuild legs
                    if(w>0) {
                        if(w<this.legs.length) {
                            this.legs[w].srcPoint=this.waypoints[w-1].point;
                            this.legs[w].dstPoint=this.waypoints[w+1].point;
                            this.legs[w].compute(vmedia.value,cmedio.value);
                        }
                        this.legs.splice(w-1,1);
                    }
                    else this.legs.splice(w,1);
                    // remove waypoint
                    this.waypoints.splice(w,1);
                    // remove things
                    GEvent.clearInstanceListeners(overlay);
                    this.qmap.removeOverlay(overlay);
                    this.UpdateFlightRoute();
                    break;
                }
            }
        }
    }
    

    //add listeners
    GEvent.addListener(this.qmap,"click",OnMapClick);
    GEvent.addListener(this.qmap,"singlerightclick",OnMapRightClick);        
    GEvent.addListener(this.qmap,"mousemove",OnMapMouseMove);        
    
   
    // PAGE EVENT HANDLERS
    
    // OnResetMap handler
    this.OnResetMap = function() {
        while(this.waypoints.length) {
            var wpt = this.waypoints.pop();
            GEvent.clearInstanceListeners(wpt.marker);
            this.qmap.removeOverlay(wpt.marker);
        }
        while(this.legs.length) this.legs.pop();
        this.UpdateFlightRoute();
    }
    
    // OnUpdateLegs handler
    this.OnUpdateLegs = function() {
        for(l in this.legs) this.legs[l].compute(vmedia.value,cmedio.value);
        this.UpdateFlightRoute();
    }
    
    // OnAddWaypointByCoordinatesClick handler
    this.OnAddWaypointByCoordinatesClick = function(latlng) {
        this.waypoints.push(new QWaypoint(latlng,null,this.icon));
        if(this.waypoints.length>1) {
            var lg = new leg();
            lg.srcPoint=this.waypoints[this.waypoints.length-2].point;
            lg.dstPoint=this.waypoints[this.waypoints.length-1].point;
            lg.compute(vmedia.value,cmedio.value);
            this.legs.push(lg);
        }
        this.UpdateFlightRoute();
    }
    
    // OnAddWaypointByAirfield handler
    this.OnAddWaypointByAirfield = function(overlay) {
        for(f=0; f<this.es.length; f++) {
            if(this.es[f]==overlay) {
                var wpt = new QWaypoint(this.es[f].getLatLng(),this.esnames[f],this.es[f].getIcon());
                this.waypoints.push(wpt);                
                if(this.waypoints.length>1) {
                    var lg = new leg();
                    lg.srcPoint=this.waypoints[this.waypoints.length-2].point;
                    lg.dstPoint=this.waypoints[this.waypoints.length-1].point;
                    lg.compute(vmedia.value,cmedio.value);
                    this.legs.push(lg);
                }
                this.UpdateFlightRoute();
                break;
            }            
        }
    }
    
    // OnShowSpanishAirfieldsClick handler
    this.es = new Array(); // spanish airfields markers array
    this.esnames = new Array();
    this.esmgr = null; // es airfields marker manager
    this.OnShowSpanishAirfieldsClick = function(bShow) {
        if(bShow) {
            if(this.es.length==0) {
                if(this.esmgr==null) this.esmgr = new GMarkerManager(this.qmap,{trackMarkers:true});
                var xmles = new ActiveXObject("Microsoft.XMLDOM");
                xmles.async=false;
                /*
                xmles.load("http://www.diariodevuelo.com/airfields.kml");
                //xmles.loadXML(xmlAirfields.innerHTML);
                var fields = xmles.selectNodes("//Folder[name=\"Spain\" or name=\"Portugal\"]/Placemark");
                //var fields = xmles.selectNodes("//Campos[IdCountry=\"1\"]");
                for(f=0; f<fields.length; f++) {
                    var strName = fields[f].selectSingleNode("name").text;
                    //var strName = fields[f].selectSingleNode("Nombre").text;
                    strName += " - " + fields[f].selectSingleNode("description").text;
                    var coords = fields[f].selectSingleNode("Point/coordinates").text;
                    coords = coords.split(",");
                    //var X = fields[f].selectSingleNode("CoordenadaX").text;
                    //var Y = fields[f].selectSingleNode("CoordenadaY").text;
                    if(coords.length>1) {
                        var marker = new GMarker(new GLatLng(parseFloat(coords[1]),parseFloat(coords[0])),this.iconPlane);
                        //var marker = new GMarker(new GLatLng(parseFloat(Y),parseFloat(X)),this.iconPlane);
                        marker.bindInfoWindowHtml(strName);
                        this.es.push(marker);
                        this.esnames.push(strName);
                    }
                }
                this.esmgr.addMarkers(this.es,8);
                */
                 xmles.load("http://www.diariodevuelo.com/airfields.spain.portugal.kml");
                //xmles.loadXML(xmlAirfields.innerHTML);
                var fields = xmles.selectNodes("//ViewCampos");
                //var fields = xmles.selectNodes("//Campos[IdCountry=\"1\"]");
                for(f=0; f<fields.length; f++) {
                    var strName = fields[f].selectSingleNode("Nombre").text;
                    if(fields[f].selectSingleNode("CoordenadaX")!=null && fields[f].selectSingleNode("CoordenadaY")!=null) {
                        var X = fields[f].selectSingleNode("CoordenadaX").text;
                        var Y = fields[f].selectSingleNode("CoordenadaY").text;
                        var marker = new GMarker(new GLatLng(parseFloat(Y),-parseFloat(X)),this.iconPlane);
                        marker.bindInfoWindowHtml(strName);
                        this.es.push(marker);
                        this.esnames.push(strName);
                    }
                }
                this.esmgr.addMarkers(this.es,8);
           }
            this.esmgr.refresh();
        }
        else {
            for(m=0; m<this.es.length; m++) this.qmap.removeOverlay(this.es[m]);
        }
    }
}

// listeners
function OnMapClick(overlay, point) {
    return qfr.OnMapClick(overlay,point);
}

function OnMapRightClick(point, src, overlay) {
    return qfr.OnMapRightClick(point, src, overlay);
}

function OnMapMouseMove(latlng) {
    cellLatlng.innerHTML="Lat:" + latlng.lat().toFixed(8) + " Lng:" + latlng.lng().toFixed(8);
}

// the one and only QFlightRoute object
var qfr;

var xmlNoUlm;

// PAGE EVENT HANDLERS

function initialize() {
  if (GBrowserIsCompatible()) {
    // initialize map
    qfr = new QFlightRoute(document.getElementById("mymap"),new GLatLng(40,-3), 6, tableroute);
    //
    xmlNoUlm = new ActiveXObject("Microsoft.XMLDOM");
    xmlNoUlm.async=false;
    xmlNoUlm.load("http://www.diariodevuelo.com/noulmairspace.kml");
    ShowZones("DANGER","#FF8800");
    ShowZones("PROHIBITED","#FF0000");
    ShowZones("RESTRICTED","#FF00FF");
    ShowZones("CLASSA","#FF0000");
    ShowZones("CLASSB","#FF0000");
    ShowZones("CLASSC","#FF0000");
    ShowZones("CLASSD","#FF0000");
    ShowZones("CLASSE","#FF0000");
    /*
    var zones = xmlNoUlm.selectNodes("//Placemark");
    for(z=0; z<zones.length; z++) {
        var vertexes = new Array();
        var strName = zones[z].selectSingleNode("description").text;
        var strCoords = zones[z].selectSingleNode(".//coordinates").text;
        var coords = strCoords.split(" ");
        for(c=0; c<coords.length; c++) {
            var xyz = coords[c].split(",");
            if(xyz.length>1) {
                vertexes.push(new GLatLng(parseFloat(xyz[1]),parseFloat(xyz[0])));
            }
        }
        if(vertexes.length>2) {
            var polygon = new GPolygon(vertexes,"#FF0000",2,0.6,"#FF8888",0.25);
            //marker.bindInfoWindowHtml(strName);
            qfr.qmap.addOverlay(polygon);
       }
     }
     */
  }
}

function ShowZones(type,color)
{
    var zones = xmlNoUlm.selectNodes("//"+ type + "/Placemark");
    for(z=0; z<zones.length; z++) {
        var vertexes = new Array();
        var strName = zones[z].selectSingleNode(".//description").text;
        var strCoords = zones[z].selectSingleNode(".//Polygon/coordinates").text;
        var coords = strCoords.split(" ");
        for(c=0; c<coords.length; c++) {
            var xyz = coords[c].split(",");
            if(xyz.length>1) {
                vertexes.push(new GLatLng(parseFloat(xyz[1]),parseFloat(xyz[0])));
            }
        }
        if(vertexes.length>2) {
            var polygon = new GPolygon(vertexes,color,2,0.6,color,0.25, {'clickable': false});
            qfr.qmap.addOverlay(polygon);
        }
       
        var strPoint = zones[z].selectSingleNode(".//Point/coordinates").text
        var point = strPoint.split(",");
        if(point.length>1) {
            var marker = new GMarker(new GLatLng(parseFloat(point[1]),parseFloat(point[0])),qfr.iconPoint);
            marker.bindInfoWindowHtml(strName);
            qfr.qmap.addOverlay(marker);
        }
        
     }
}

function OnResetMap() {
    qfr.OnResetMap();
}

function OnUpdateLegs() {
    qfr.OnUpdateLegs();
}

function OnAddWaypointByCoordinatesClick() {
    var lat = parseFloat(txtLat.value);
    var lng = parseFloat(txtLng.value);
    if(!(isNaN(lat) || isNaN(lng))) qfr.OnAddWaypointByCoordinatesClick(new GLatLng(lat,lng));
}

function OnShowSpanishAirfieldsClick() {
    qfr.OnShowSpanishAirfieldsClick(bShowAirfields.checked);
}

