
//  NEW VERSION
//  new global variables (should belong to package mtp_track)
var mtp_track_LegIdx;
var mtp_track_LegTimeoutRef;
var mtp_track_Object;


function mtp_track_LoadHandler(obj_ref) {
    var request = obj_ref.i_rest_request;
    if (request.readyState != 4) { return; }
    
    //  Parse Track
    if (obj_ref.Parse(request.responseText)) {
        //  The data received from the REST web service has been parsed.
        //  Now the map with the track can be displayed
        obj_ref.Show();

    }
}

function mtp_directions_LoadHandler(obj_ref) {
    //  Reset the timeout (to re-load the current leg)
    clearTimeout(mtp_track_LegTimeoutRef);

    //  a GPolyline is obtained from the g_directions (global object) GDirections object
    var gp = obj_ref.i_directions.getPolyline();

    //  build our own polyline
    var pts = [];
    for (var i = 0; i < gp.getVertexCount(); i++) {
        pts[i] = gp.getVertex(i);
    }

    var ourpoly = new GPolyline(pts, "#0000ff", 5);
    obj_ref.i_polys.push(ourpoly);
    obj_ref.i_map.addOverlay(ourpoly);

    obj_ref.i_cur_index++;
    if (obj_ref.i_cur_index >= obj_ref.i_waypoints.length) {
        obj_ref.OnLegDone(obj_ref.i_name, obj_ref.i_length);
        return;
    }

    //  status bar
    obj_ref.OnLegLoading(obj_ref.i_name, obj_ref.i_cur_index, (obj_ref.i_waypoints.length - 1));
    
    //  there are more polylines to be shown
    obj_ref.LoadDirection(obj_ref.i_cur_index - 1);

}

function mtp_track_LegTimeout() {
    //  This function tries to reload the leg that went on timeout
    if (mtp_track_Object) {
        mtp_track_Object.OnLegTimeout(mtp_track_Object.i_name, mtp_track_LegIdx);
        //show_timeout(mtp_track_LegIdx);
        clearTimeout(mtp_track_LegTimeoutRef);
        mtp_track_Object.LoadDirection(mtp_track_LegIdx);
    }        
}


//  new release (mtp_track class)
function mtp_track(map_obj_ref) {
    var self = this;
    
    //========================================================================
    //  class properties
    //========================================================================
    this.i_map = map_obj_ref;       //  reference to a GMap2 object
    this.i_waypoints = null;        //  array holding the defined waypoints
    this.i_region = "n.a.";         //  region code/name
    this.i_country = "n.a.";        //  country code/name
    this.i_name = "n.a.";           //  track name (as given by the author)
    this.i_mc_lat = 0.0;            //  track map center latitude (as defined by the author)
    this.i_mc_lng = 0.0;            //  track map center longitude (as defined by the author)
    this.i_mz = 8;                  //  track map zoom (as defined by the author)
    this.i_marker = null;           //  reference to the marker that is related to this track
    this.i_uid = 0;                 //  unique index identifying this track as assigned by the server
    this.i_author_id = 0;           //  unique index of the author of this track as assigned by the server
    this.i_author_nickname = "n.a.";//  nickname of the author of this track
    this.i_track_id = 0;            //  index valid amongst the tracks set created by the author of this track
    this.i_usage = 0;               //  number of challengers' GPX files that have been uploaded for this track
    this.i_race_data = false;       //  flag indicating if the race data has been loaded (true = loaded)
    this.i_length = 0.0;            //  length of the track
    this.i_icon_wp = null;          //  reference to the icon used for standard waypoint rendering
    this.i_icon_start = null;       //  reference to the icon used for start waypoint rendering
    this.i_icon_end = null;         //  reference to the icon used for end waypoint rendering
    this.i_marker_manager = null;   //  internal marker manager to hold the track's waypoints
    this.i_polys = null;
    this.i_directions = null;
    this.i_cur_index = 0;
    this.i_status = 0;              //  0: not loaded 1: loading 2: loaded

    this.i_nav_index = 0;           //  used to support (next and prev)
    this.i_nav_marker_manager = null;
    this.i_icon_nav = null;
    
    //  Ajax related
    this.i_rest_request = null;



    //  icons initialization
    //  i_icon_wp
    this.i_icon_wp = new GIcon();
    this.i_icon_wp.image = '/images/node.bmp';
    this.i_icon_wp.shadow = '';
    this.i_icon_wp.iconSize = new GSize(10, 10);
    this.i_icon_wp.shadowSize = new GSize(0, 0);
    this.i_icon_wp.iconAnchor = new GPoint(5, 5);
    this.i_icon_wp.infoWindowAnchor = new GPoint(5, 5);
    this.i_icon_wp.dragCrossImage = 'empty.gif';    // undocumented String: indicates an image to be used as the drag cross. If you set it to the null string, you get the default drag_cross_67_16.png image.
    this.i_icon_wp.dragCrossSize = GSize(1, 1);     //undocumented GSize(): indicates the size of the drag cross.
    this.i_icon_wp.maxHeight = 1;                   //undocumented integer: The maximum difference in height between the marker anchor and the drag cross anchor during dragging. Setting the maxHeight to zero causes it to use the default 13.

    //  i_icon_start
    this.i_icon_start = new GIcon();
    this.i_icon_start.image = '/images/dd-start-wl.png';
    this.i_icon_start.shadow = '';
    this.i_icon_start.iconSize = new GSize(26, 26);
    this.i_icon_start.shadowSize = new GSize(0, 0);
    this.i_icon_start.iconAnchor = new GPoint(0, 26);
    this.i_icon_start.infoWindowAnchor = new GPoint(5, 5);
    this.i_icon_start.dragCrossImage = 'empty.gif';
    this.i_icon_start.dragCrossSize = GSize(1, 1);
    this.i_icon_start.maxHeight = 1;

    //  i_icon_end
    this.i_icon_end = new GIcon();
    this.i_icon_end.image = '/images/dd-end-wl.png';
    this.i_icon_end.shadow = '';
    this.i_icon_end.iconSize = new GSize(26, 26);
    this.i_icon_end.shadowSize = new GSize(0, 0);
    this.i_icon_end.iconAnchor = new GPoint(26, 26);
    this.i_icon_end.infoWindowAnchor = new GPoint(5, 5);
    this.i_icon_end.dragCrossImage = 'empty.gif';
    this.i_icon_end.dragCrossSize = GSize(1, 1);
    this.i_icon_end.maxHeight = 1;

    //  for nav tools
    this.i_icon_nav = new GIcon();
    this.i_icon_nav.image = '/images/nav-marker-wl.png';
    this.i_icon_nav.shadow = '';
    this.i_icon_nav.iconSize = new GSize(24, 24);
    this.i_icon_nav.shadowSize = new GSize(0, 0);
    this.i_icon_nav.iconAnchor = new GPoint(12, 12);
    this.i_icon_nav.infoWindowAnchor = new GPoint(12, 12);
    this.i_icon_nav.dragCrossImage = 'empty.gif';
    this.i_icon_nav.dragCrossSize = GSize(1, 1);
    this.i_icon_nav.maxHeight = 1;
    
    

    //========================================================================
    //  class methods
    //========================================================================
    this.Reset = function() {

        //  reset array, values etc.
        if (this.i_marker_manager) {
            this.i_marker_manager.clearMarkers();
        }

        if (this.i_nav_marker_manager) {
            this.i_nav_marker_manager.clearMarkers();
        }
        this.i_nav_index = 0;

        if (this.i_waypoints != null) {
            //  reset the i_waypoints array
            while (this.i_waypoints.length > 0) { this.i_waypoints.pop(); }
            this.i_waypoints = null;
        }

        //  note:   the marker is not reset
        this.i_region = "n.a.";
        this.i_country = "n.a.";
        this.i_name = "n.a.";
        this.i_mc_lat = 0.0;
        this.i_mc_lng = 0.0;
        this.i_mz = 8;
        this.i_uid = 0;
        this.i_author_id = 0;
        this.i_author_nickname = "n.a.";
        this.i_track_id = 0;
        this.i_usage = 0;
        this.i_race_data = false;
        this.i_length = 0.0;
        this.i_status = 0;      // track not loaded

        return;
    }

    this.Parse = function(server_reply) {
        
        //  This method parses the reply incoming from the server (REST Web Service).
        //  o_track "server_reply" is the text-reply generated by the web service
        
        

        //  Parse the response from the server
        var a_track = new Array();
        a_track = server_reply.split(";");

        //  a_track contains all the records originally present in the track definition file
        var token = "";
        var value = "";
        for (i = 0; i < a_track.length; i++) {

            //  parse each record
            //  tokens: er, mc, mz, wp, ch

            token = a_track[i].substr(0, 3);     //  token
            value = a_track[i].substr(3);       //  value


            if (token == "er=") {
                //  TODO
                //  Error management
                return false;
            }
            else if (token == "mc=") {
                //  Map Center latitude and longitude
                var latlong = value.split(",");
                this.i_mc_lat = parseFloat(latlong[0]);
                this.i_mc_lng = parseFloat(latlong[1]);
            }
            else if (token == "mz=") {
                //  Map Zoom factor
                this.i_mz = parseInt(value);
            }
            else if (token == "wp=") {
                //  Track Waypoint
                if (this.i_waypoints == null) { this.i_waypoints = new Array(); }
                var latlong = value.split(",");
                this.i_waypoints.push(new GLatLng(parseFloat(latlong[0]), parseFloat(latlong[1]), true));
            }
            else if (token == "ti=") {
                //  Track Index
                this.i_track_id = value;
            }
            else if (token == "tn=") {
                //  Track Name
                var encoded_name = value.split(".");
                this.i_name = "";
                for (ii = 0; ii < encoded_name.length; ii++) {
                    this.i_name = this.i_name + String.fromCharCode(parseInt(encoded_name[ii]));
                }
            }
            else if (token == "tl=") {
                this.i_length = parseFloat(value);
            }
            else if (token == "cn=") {
                this.i_country = value;
            }
            else if (token == "cr=") {
                this.i_region = value;
            }
        }

        if (this.i_name == "") { this.i_name = this.i_track_id; }
        this.i_status = 2;  //  track loaded     
        return true;
    }

    this.Load = function(marker_ref, track_uuid, user_idx, race_idx) {
        //  this function loads the race created by the user (useridx) and with user index (raceidx)
        this.Reset();
        
        this.i_status = 1;  // track loading
        this.i_marker = marker_ref;
        this.i_uid = track_uuid;        
        this.i_author_id = user_idx;
        this.i_track_id = race_idx;
                
        this.i_rest_request = createXMLHttpRequest();
        if (this.i_rest_request == null) { return false; }

        //  send the request
        var rest_request = "/scripts/wl_load_track.php?u=" + this.i_author_id + "&r=" + this.i_track_id;
        this.i_rest_request.open("GET", rest_request, true);

        this.i_rest_request.onreadystatechange = function() { mtp_track_LoadHandler(self); }
        this.i_rest_request.send(null);

        return true;
    }


    this.ShowWaypoints = function() {
        //  the method renders the track waypoints (the wps are added to the track's marker manager)
        if (this.i_map == null)  { return; }
        if (this.i_marker_manager == null) { return; }
        
        var wps = new Array();
        var marker = null;
        for (var i = 0; i < this.i_waypoints.length; i++) {
            if (i == 0) { marker = new GMarker(this.i_waypoints[i], this.i_icon_start); }                                   // marker for the first waypoint 
            else if (i == (this.i_waypoints.length - 1)) { marker = new GMarker(this.i_waypoints[i], this.i_icon_end); }    // marker for the last waypoint
            else {marker = new GMarker(this.i_waypoints[i], { icon: this.i_icon_wp }); }
            
            wps.push(marker);
        }
        
        if (wps.length > 0)
        {
            this.i_marker_manager.addMarkers(wps, 10);            
            while (wps.length > 0) { wps.pop(); }
        }
        
        this.i_marker_manager.refresh();
    }
    
    this.LoadDirection = function (idx) {
        //  this method loads the direction between waypoint idx and waypoint idx+1
        if (this.i_directions == null) { return; }
        if (this.i_waypoints == null) { return; }
        
        //  mtp_track_LegIdx is global
        mtp_track_LegIdx = idx;

        //  mtp_track_Object is global
        mtp_track_Object = self;
        
        //  TODO - check if with the Timeout it is possible to use self (as for the other handlers)
        //  mtp_track_LegTimeoutRef is global
        mtp_track_LegTimeoutRef = setTimeout("mtp_track_LegTimeout()", 2000);
        this.i_directions.loadFromWaypoints([this.i_waypoints[idx].toUrlValue(6), this.i_waypoints[idx + 1].toUrlValue(6)], { getPolyline: true }, { travelMode: G_TRAVEL_MODE_WALKING });
    }
    
    
    this.ShowLegs = function() {
        //  reset and initialize g_polys
        if (this.i_polys == null) { this.i_polys = new Array(); }
        else { while (this.i_polys.length > 0) { this.i_polys.pop(); } }

        //  reset and initialize g_directions
        if (this.i_directions == null) {
            //  The listener has to be added just once, otherwise it will be called several times
            this.i_directions = new GDirections();
            GEvent.addListener(this.i_directions, "load", function() {mtp_directions_LoadHandler(self)} );
        }

        this.i_cur_index = 1;
        this.OnLegLoading(this.i_name, this.i_cur_index, (this.i_waypoints.length - 1));
        this.LoadDirection(this.i_cur_index-1);
    }
    

    this.Show = function() {
        //  the method rebders the track: waypoints and legs
        if (this.i_map == null)  { return false; }
        
        if (this.i_marker_manager == null) {
            // create the marker manager used for the track's waypoints
            this.i_marker_manager = new MarkerManager(this.i_map);
        } else {
            // reset the current marker manager
            this.i_marker_manager.clearMarkers();
        }
        
            
        //  set the center and the zoom of the map as defined in the original track definition file
        this.i_map.setCenter(new GLatLng(this.i_mc_lat, this.i_mc_lng), this.i_mz);

        //  Show all the track waypoints
        this.ShowWaypoints();

        //  display the track
        this.ShowLegs();
        
        return true;
    }

    //  Navigation tool
    this.ShowNav = function (index) {
        if (this.i_map) {
            if (this.i_waypoints.length > index) {
                this.i_map.setCenter(this.i_waypoints[index], 12);

                //  initialize the marker manager used for the nav tools
                if (this.i_nav_marker_manager == null) { this.i_nav_marker_manager = new MarkerManager(this.i_map); }
                else { this.i_nav_marker_manager.clearMarkers(); }

                //  put here the new nav tool marker
                var marker = new GMarker(this.i_waypoints[index], this.i_icon_nav);
                this.i_nav_marker_manager.addMarker(marker, 10);

                //  refresh the marker manager
                this.i_nav_marker_manager.refresh();
            }
        }    
    }

    this.NavStart = function() {
        //  Goto to the track start point (first waypoint) and apply a "proper" zoom
        this.i_nav_index = 0;
        this.ShowNav(this.i_nav_index);
        return;
    }

    this.NavNext = function() {
        if (this.i_waypoints == null) { return; }
        if (this.i_nav_index >= this.i_waypoints.length) { return; }
        this.i_nav_index++;
        this.ShowNav(this.i_nav_index);
        return;
    }

    this.NavPrev = function() {
        if (this.i_nav_index < 1) { return; }
        this.i_nav_index--;
        this.ShowNav(this.i_nav_index);
        return;
    }

    this.NavEnd = function() {
        if (this.i_waypoints == null) { return; }
        this.i_nav_index = this.i_waypoints.length - 1;
        this.ShowNav(this.i_nav_index);
        return;
    }
    
    
    //  Handlers
    this.OnLegTimeout = function(track_name, leg_idx) {
        //  Handler to display the "Reloading" msg due to a timeout        
        return;
    }
    this.OnLegLoading = function(track_name, leg_idx, leg_tot) {
        //  handler to display the "Loading" msg
        return;        
    }
    this.OnLegDone = function(track_name, track_length) {
        //  called when all the legs have been loaded
        return;
    }        
}


