/*
* Google map warper for load and display ajax xml data transport
* @authur  Chayakon PONGSIRI
* 
*  @example
*  var map = new InnoGoogleMap("map",8.489351,98.550797,9);
*  map.loadMapData(url);
*
*/

  /*
  * InnoGoogleMap class 
  * @param mapElementId    the html element container for display map
  * @param lat             defalult center map latitude
  * @param lng             defalult center map longitude
  * @param zoom            defalult zoom level
  */
  function InnoGoogleMap(mapElementId ,lat , lng , zoom){
      var _elementid = mapElementId;
      var _latitude = lat;
      var _longitude = lng;
      var _zoom = zoom;
      var _map;
      var _point = new GLatLng( lat, lng);
      // create the map
      _map = new GMap2(document.getElementById(mapElementId));
      _map.addControl(new GLargeMapControl());
      _map.addControl(new GMapTypeControl());
      _map.setCenter(_point, _zoom);

      /**
      * get google map object
      */
      InnoGoogleMap.prototype.getGMap = function(){
         return _map;
      }

      /**
      * get current point
      */
      InnoGoogleMap.prototype.getCenterMap = function(){
         return _point;
      }
      /*
      * set Center map
      */
      InnoGoogleMap.prototype.setCenterMap = function(lat , lng){
        _point = new GLatLng( lat, lng);
        _map.setCenter(_point, _zoom);
      }
      /*
      * for load marker from specified url
      * the old marker also remove
      */
      InnoGoogleMap.prototype.loadMapData = function(url){
        if (url == null)
        {
          alert('ERROR : url can not be null in loadMapData(url)');
          return false;
        }
        // hide the info window, otherwise it still stays open where the removed marker used to be
        _map.getInfoWindow().hide();
        _map.clearOverlays();            
        // Read the data from example.xml
        GDownloadUrl(url, this.GDownloadUrlCallback );
      }
      /*
      * for load marker from specified url
      * and append marker
      */
      InnoGoogleMap.prototype.loadMapDataAndAppend = function(url){
        if (url == null)
        {
          alert('ERROR : url can not be null in loadMapData(url)');
          return false;
        }
        // hide the info window, otherwise it still stays open where the removed marker used to be
        _map.getInfoWindow().hide();

        // Read the data from example.xml
        GDownloadUrl(url, this.GDownloadUrlCallback );
      }
      /**
      * call back function for GDownloadUrl
      */
      InnoGoogleMap.prototype.GDownloadUrlCallback = function(doc){
          var xmlDoc = GXml.parse(doc);
          var objectDataArray = parseData(xmlDoc);
          var output = '';
          for (var i = 0; i < objectDataArray.length; i++) {
            var objectData = objectDataArray[i];
            var marker = createMarkerFromObject(objectData);
            _map.addOverlay(marker);
          }
      }
      /**
      * for create dragable marker with specify html element id
      * @example
      *    var map = new InnoGoogleMap("map",7.85,98.42,9);
      *    var markerObject = new Object();
      *    markerObject.latitude = 7.8;
      *    markerObject.longitude = 98.3;
      *    map.createDragableMarker(markerObject,"html_lat","html_lng");
      */
      InnoGoogleMap.prototype.createDragableMarker = function(objectData,eleLatId,eleLonId){
        var lat_element = document.getElementById(eleLatId);
        var lng_element = document.getElementById(eleLonId);
        var point = new GLatLng( objectData.latitude, objectData.longitude);
        if (lat_element == null || lng_element == null)
        {
            alert("ERROR: can't get element by id of " + eleLatId + ", or " + eleLonId );
            return false;
        }
        var marker = new GMarker(point, {draggable: true});  
        _map.addOverlay(marker);
        lat_element.value = point.lat();
        lng_element.value = point.lng();
        GEvent.addListener(marker, "dragend", function() {
          var p = marker.getPoint();
          _map.panTo(p);
          lat_element.value = p.lat();
          lng_element.value = p.lng();
        });
      }
      /**
      * for create marker 
      */
      InnoGoogleMap.prototype.createMarker = function(objectData){
        //TODO implement the create marker
        if (objectData == null)
        {
            alert("ERROR: objectData can't be null");
            return false;
        }
      }
      /** 
      * create info window
      * @param lat  double latitude
      * @param lng  double longitude
      * @param detail string the detail to display in infoWindow
      */
      InnoGoogleMap.prototype.createInfoWindow = function(lat,lng,detail){
        _map.openInfoWindow(new GLatLng( lat, lng),document.createTextNode(detail));
      }
  }


  /*
  * A function to create a tabbed marker and set up the event window
  * This version accepts a variable number of tabs, passed in the arrays htmls[] and labels[]
  */
  function createMarkerFromObject(objectData) {
    var point = new GLatLng(objectData.latitude,objectData.longitude);
    var marker = null;
    //set icon
    if (objectData != null && objectData.icon != null && objectData.icon.length)
    {
      var gicon = new GIcon(G_DEFAULT_ICON);
      gicon.image = objectData.icon;
      gicon.shadow = objectData.icon_shadow;
      //gicon.iconSize = new GSize(12, 20);
      //gicon.iconAnchor = new GPoint(12, 20);
      marker = new GMarker(point, { icon:gicon });
    }else{
      marker = new GMarker(point);
    }


    GEvent.addListener(marker, "click", function() {
      // adjust the width so that the info window is large enough for this many tabs
      if (objectData.details.length > 2) {
        objectData.details[0].text = '<div style="width:'+objectData.details.length*88+'px">' + objectData.details[0].text + '</div>';
      }else{
        objectData.details[0].text = '<div style="width:300px">' + objectData.details[0].text + '</div>';
      }
      var tabs = [];
      for (var i=0; i<objectData.details.length; i++) {
        tabs.push(new GInfoWindowTab(objectData.details[i].label,objectData.details[i].text));
      }
      marker.openInfoWindowTabsHtml(tabs);
    });
    return marker;
  }
  /*
  * for convert xml dom to marker object
  * object data definition
  *   marker.latitude       float   latitude
  *   marker.longitude      float   longitude 
  *   marker.title          string  
  *   marker.icon           string
  *   marker.icon_shadow    string
  *   marker.details[]        array of object   for display as tab 
  *   marker.details[].label  string   tab title
  *   marker.details[].text   string   detail
  * @param xmlDoc   the xml document
  * @return marker array of marker object
  */
  function parseData(xmlDoc){
    var markerArray = new Array();
    var marker = null;

    var markerNode = xmlDoc.documentElement.getElementsByTagName("marker");
    var output = '';

    for (var i = 0; i < markerNode.length; i++) {
      marker = new Object();
      marker.nodeName   = '';
      marker.latitude   = 0.0;
      marker.longitude  = 0.0;
      marker.title      = '';
      marker.icon       = '';
      marker.icon_shadow  = '';
      marker.details  = null;
      for (var j = 0; j < markerNode[i].childNodes.length; j++)
      {
        var node = markerNode[i].childNodes[j];
        
        if (node.nodeType == 1)
        {
          var child = node.firstChild;
          if (child != null)
          {
            marker.nodeName = node.nodeName;
            if (node.nodeName == 'latitude'){
              marker.latitude = parseFloat(trim(child.nodeValue));
            }else if (node.nodeName == 'longitude'){
              marker.longitude = parseFloat(trim(child.nodeValue));
            }else if (node.nodeName == 'title'){
              marker.title = trim(child.nodeValue);
            }else if (node.nodeName == 'icon'){
              marker.icon = trim(child.nodeValue);
            }else if (node.nodeName == 'icon_shadow'){
              marker.icon_shadow = trim(child.nodeValue);
            }else if (node.nodeName == 'model'){
              marker.model = trim(child.nodeValue);
            }else if (node.nodeName == 'details'){
              var details = node.childNodes;
              marker.details = new Array();
              
              //load detail tab
              for(var k = 0; k < details.length; k++){
                var detailElement = details[k].firstChild;
                if (detailElement != null)
                {
                  var detailValue = detailElement.nodeValue;
                  
                  //if detail.trim().length > 0 then add detail array
                  if (detailValue != null && detailValue.replace(/^\s+|\s+$/g, '').length > 0)
                  {
                    var label = details[k].getAttribute('label');
                    detailObject = new Object();
                    detailObject.label = trim(label);
                    detailObject.text = detailElement.nodeValue;
                    //add to detail list
                    marker.details.push(detailObject);
                    //document.write(detail + "," + detailElement.nodeType + "," +detailValue+"<BR />");
                  }
                }
              }//end for
            }//end if
          }
        }
      }
      markerArray.push(marker);
    }//end for
    return markerArray;
  }

  function trim(str) {
        return str.replace(/^\s+|\s+$/g,"");
  }