/*
Where to get this from: http://wiki.openstreetmap.org/index.php/Openlayers_Track_example
*/

/* Copyright (c) 2006 MetaCarta, Inc., published under the BSD license.
 * See http://svn.openlayers.org/trunk/openlayers/release-license.txt 
 * for the full text of the license. */

/**
 * @class
 * 
 * @requires OpenLayers/Layer/Markers.js
 * @requires OpenLayers/Ajax.js
 */
OpenLayers.Layer.GPX = OpenLayers.Class.create();
OpenLayers.Layer.GPX.prototype = 
  OpenLayers.Class.inherit( OpenLayers.Layer.Markers, OpenLayers.Layer.Vector, {

    /** store url of text file
    * @type str */
    url:null,
    icolor:null,
    /** @type Array(OpenLayers.Feature) */
    features: null,

    /** @type OpenLayers.Feature */
    selectedFeature: null,

    /**
    * @constructor
    *
    * @param {String} name
    * @param {String} location
    */
    initialize: function(name, url, icolor, options) {
    var newArguments = new Array()
    newArguments.push(name, options);
    OpenLayers.Layer.Vector.prototype.initialize.apply(this, newArguments);
        OpenLayers.Layer.Markers.prototype.initialize.apply(this, [name]);
        this.url = url;
        this.icolor = icolor;
        this.features = new Array();
    var results = OpenLayers.loadURL(this.url, null, this, this.requestSuccess, this.requestFailure);
    },

    /**
     * 
     */

    destroy: function() {
        this.clearFeatures();
        this.features = null;
        OpenLayers.Layer.Markers.prototype.destroy.apply(this, arguments);
    },
        
    /**
     * @param {XMLHttpRequest} ajaxRequest
     */
    requestSuccess:function(request) {
    var gpxns = "http://www.topografix.com/GPX/1/0";
        var doc = request.responseXML;
        if (!doc || request.fileType!="XML") {
            doc = OpenLayers.parseXMLString(request.responseText);
        }
        if (typeof doc == "string") {
            doc = OpenLayers.parseXMLString(doc);
        }
    
    /* search and display track */
//  var trk = OpenLayers.Ajax.getElementsByTagNameNS(doc, gpxns, "", "trk");
  var trk = doc.getElementsByTagName("trk");    
    var featureTRK = [];
    for (var i = 0; i< trk.length; i++) {
//    var color = '#00FF00';         // Fix Color
//    var color=this.randomColor();  // Random Color
      var color=this.icolor;  // Random Color
        for (var j = 0; j < trk[i].childNodes.length; j++) {
                        switch (trk[i].childNodes[j].nodeName)
                        {
                                case 'topografix:color':
                                        color = '#' + OpenLayers.Util.getXmlNodeValue(trk[i].childNodes[j]);
                                        break;
                                case 'trkseg':
                    if (color == '')
                        color=this.randomColor();
                                        featureTRK.push(this.addLineGPX(trk[i].childNodes[j], color));
                                        break;
                                case '#text':
                                        break;
                                case 'name':
//FIXME: label the way
                                        break;
                                default:
//                                      alert('unknown ' + trk[i].childNodes[j].nodeName);
                                        break;
                        }
                }
        }
    this.addFeatures(featureTRK);
    /* search and display route */
//  var rte = OpenLayers.Ajax.getElementsByTagNameNS(doc, gpxns, "", "rte");
  var rte = doc.getElementsByTagName("rte");        
    var featureRTE = [];
    for (var i = 0; i< rte.length; i++) {
        var color = this.randomColor();
        var style_green = {
            strokeColor: color,
            strokeOpacity: 1,
            strokeWidth: 4,
            pointRadius: 6,
            pointerEvents: "visiblePainted"
        };
        var pointList = [];
        for (var j = 0; j < rte[i].childNodes.length; j++) {
            switch (rte[i].childNodes[j].nodeName)
            {
                case 'rtept':
                    var feature = this.parseFeature(rte[i].childNodes[j]);
                    if (feature) {
                        pointList.push(feature);
                    }
                    break;
                default:
                    break;
            }
                }
        featureRTE.push(new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(pointList),null,style_green));
        };
    this.addFeatures(featureRTE);

    /* search and display waypoint */
//  var wpt = OpenLayers.Ajax.getElementsByTagNameNS(doc, gpxns, "", "wpt");
  var wpt = doc.getElementsByTagName("wpt");        
        var featuresWPT = [];
        for (var i = 0; i< wpt.length; i++) {
        var data = {}; 
        var point = this.setToMercator(wpt[i].getAttribute('lon'),wpt[i].getAttribute('lat'));
        var location =  new OpenLayers.LonLat(point[0], point[1]);
        /* Provide defaults for title and description */
        var title = "Untitled";
        try {
            title = OpenLayers.Util.getNodes(wpt[i], 
                'name')[0].firstChild.nodeValue;
        }
        catch (e) { title="Untitled"; }

        /* GPX descriptions */
        var description = "No description.";
        try {
            description = OpenLayers.Util.getNodes(wpt[i],
                'desc')[0].firstChild.nodeValue;
        }catch (e) {
            var description = "No description.";
        }
        data.icon = OpenLayers.Marker.defaultIcon();
//      data.popupSize = new OpenLayers.Size(250, 120);
        if ((title != null) && (description != null)) {
//                if (link) contentHTML += '<a class="link" href="'+link+'" target="_blank">';
//          contentHTML += '<p>' + title + '</p>';
//                if (link) contentHTML += '</a>';
            contentHTML = '<p><strong>' + title + '</strong><br />' + description + '</p>';
            data['popupContentHTML'] = contentHTML;
        }
        var featureWPT = new OpenLayers.Feature(this, location, data);
            featuresWPT.push(featureWPT);
              var marker = featureWPT.createMarker();
         marker.events.register('click', featureWPT, this.markerClick);
              this.addMarker(marker);
        }

//        for (var i = 0; i < itemlist.length; i++) {
//---
//
//            /* If no link URL is found in the first child node, try the
//               href attribute */
//            try {
//              var link = OpenLayers.Util.getNodes(itemlist[i], "link")[0].firstChild.nodeValue;
//            } 
//            catch (e) {
//              try {
//                var link = OpenLayers.Util.getNodes(itemlist[i], "link")[0].getAttribute("href");
//              }
//              catch (e) {}
//            }
//        }
    },
    /**
     * @param {Event} evt
     */
    randomColor: function() {
    var hex=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F");
    var color = '#';
    for (i=0;i<6;i++){
        color += hex[Math.floor(Math.random()*hex.length)];
    }
    return color;
    },
    markerClick: function(evt) {
        sameMarkerClicked = (this == this.layer.selectedFeature);
        this.layer.selectedFeature = (!sameMarkerClicked) ? this : null;
        for(var i=0; i < this.layer.map.popups.length; i++) {
            this.layer.map.removePopup(this.layer.map.popups[i]);
        }
        if (!sameMarkerClicked) {
            var popup = this.createPopup(true);
            OpenLayers.Event.observe(popup.div, "click",
            function() { 
              for(var i=0; i < this.layer.map.popups.length; i++) { 
                this.layer.map.removePopup(this.layer.map.popups[i]); 
              } 
            }.bindAsEventListener(this));
            this.layer.map.addPopup(popup); 
        }
        OpenLayers.Event.stop(evt);
    },
    addLineGPX: function(xmlNode, color) {
        var style_green = {
                strokeColor: color,
                strokeOpacity: 0.6,
                strokeWidth: 5,
                pointRadius: 6,
                pointerEvents: "visiblePainted"
        };
        var pointList = [];
        for (var i = 0; i < xmlNode.childNodes.length; i++) {
//  for (var i = 0; i < 4; i++) {
                if (xmlNode.childNodes[i].nodeName == "trkpt")
                {
                        var feature = this.parseFeature(xmlNode.childNodes[i]);
                        if (feature) {
                                pointList.push(feature);
                        }
                }
        };
        return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(pointList),null,style_green);
    },

     /**
      * This function is the core of the GPX parsing code in OpenLayers.
      * It creates the geometries that are then attached to the returned
      * feature, and calls parseAttributes() to get attribute data out.
      * @param DOMElement xmlNode
      */
     parseFeature: function(xmlNode) {
        if (xmlNode.getAttribute('lat') && xmlNode.getAttribute('lon')) {
        var point = this.setToMercator(xmlNode.getAttribute('lon'),xmlNode.getAttribute('lat'));
        return new OpenLayers.Geometry.Point(point[0], point[1]);
        }
        return false;
    },
    setToMercator: function(lon, lat) {
        x = parseFloat(lon);
    y = parseFloat(lat);
    var PI = 3.14159265358979323846;
    x = x * 20037508.34 / 180;
    y = Math.log (Math.tan ((90 + y) * PI / 360)) / (PI / 180);
    y = y * 20037508.34 / 180;
    return new Array(x,y);
    },
    /**
     * 
     */
    clearFeatures: function() {
        if (this.features != null) {
            while(this.features.length > 0) {
                var feature = this.features[0];
                OpenLayers.Util.removeItem(this.features, feature);
                feature.destroy();
            }
        }        
    },
    requestFailure: function(request) {
    },
    moveTo:function(bounds, zoomChanged, dragging) { 
    OpenLayers.Layer.Vector.prototype.moveTo.apply(this, arguments);
//  OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments);
        if (!dragging) {
            this.div.style.left = - parseInt(this.map.layerContainerDiv.style.left) + "px";
            this.div.style.top = - parseInt(this.map.layerContainerDiv.style.top) + "px";
            var extent = this.map.getExtent();
            this.renderer.setExtent(extent);
        for(i=0; i < this.markers.length; i++) {
        marker = this.markers[i];
        lonlat = this.map.getLayerPxFromLonLat(marker.lonlat);
                if (marker.icon.calculateOffset) {
                    marker.icon.offset = marker.icon.calculateOffset(marker.icon.size);
                }
                var offsetPx = lonlat.offset(marker.icon.offset);
        marker.icon.imageDiv.style.left = offsetPx.x+parseInt(this.map.layerContainerDiv.style.left) + "px";
        marker.icon.imageDiv.style.top = offsetPx.y+parseInt(this.map.layerContainerDiv.style.top) + "px";
        }
        
        }
        if (!this.drawn || zoomChanged) {
            this.drawn = true;
            for(var i = 0; i < this.features.length; i++) {
                var feature = this.features[i];
                this.drawFeature(feature);
            }
        }

    },
    setMap: function(map) {
//      OpenLayers.Layer.Markers.prototype.setMap.apply(this, arguments);
        OpenLayers.Layer.prototype.setMap.apply(this, arguments);

        if (!this.renderer) {
            this.map.removeLayer(this);
        } else {
            this.renderer.map = this.map;
            this.renderer.setSize(this.map.getSize());
        }

    },
    /** @final @type String */
    CLASS_NAME: "OpenLayers.Layer.GPX"
});

