/* 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"
});