 /******************************************************************************
 *
 *  Copyright 2008-2009 David D. Emory 
 *  [additional contributors append names above] 
 *
 *  This file is part of Five Points. See <http://www.fpdev.org> for
 *  additional project information and documentation.
 *
 *  Five Points is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Five Points is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Five Points.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

/**
 * fp_trp_geocode.js
 *
 * Provides geocoding support for the Trip Planner module. Fields/functions
 * carry the "fp_tg" prefix.
 *
 * See fp_trp.php for additional documentation on the Trip Planner module.
 */


// FIELD DEFINITIONS

var fp_tgGeocodeStartAddrs_, fp_tgGeocodeEndAddrs_; // array of strings
var fp_tgGeocodeStartEncodings_, fp_tgGeocodeEndEncodings_; // array of strings
var fp_tgGeocodeStartLatLngs_, fp_tgGeocodeEndLatLngs_; // array of GLatLngs


// FUNCTION DEFINITIONS

/**
 * fp_tgGeocodeStart()
 *
 * Launches the geocoding process for the start location.
 */
function fp_tgGeocodeStart() {
  // clear the locations output
  var output = fp_outputDivs_[FP_OUTPUT_LOCATIONS];
  while (output.firstChild) output.removeChild(output.firstChild);
  
  fp_GCoder_.getLocations(document.getElementById("fp_startLocInput").value, fp_tgHandleGeocodeStartResponse);
}


/**
 * fp_tgGeocodeEnd()
 *
 * Launches the geocoding process for the end location.
 */
function fp_tgGeocodeEnd() {
  // clear the locations output
  var output = fp_outputDivs_[FP_OUTPUT_LOCATIONS];
  while (output.firstChild) output.removeChild(output.firstChild);
  
  fp_GCoder_.getLocations(document.getElementById("fp_endLocInput").value, fp_tgHandleGeocodeEndResponse);
}


/**
 * fp_tgGeocodeBoth()
 *
 * Launches the geocoding process for both the start and end locations.
 */
function fp_tgGeocodeBoth() {
  // clear the locations output
  var output = fp_outputDivs_[FP_OUTPUT_LOCATIONS];
  while (output.firstChild) output.removeChild(output.firstChild);
  
  fp_GCoder_.getLocations(document.getElementById("fp_startLocInput").value, fp_tgHandleGeocodeStartResponse);
  fp_GCoder_.getLocations(document.getElementById("fp_endLocInput").value, fp_tgHandleGeocodeEndResponse);
}


/////////////////////// START LOCATION GEOCODE FUNCTIONS ///////////////////////

/**
 * fp_tgHandleGeocodeStartResponse()
 *
 * The callback function passed to the GClientGeocoder object's getLocations() 
 * function. It parses and processes any found start location candidates. 
 *
 * -- parameters --
 * response: the response sent from the GClientGeocoder object 
 */
function fp_tgHandleGeocodeStartResponse(response) {
  if (!response || response.Status.code != 200) {
    alert("Could not resolve start address");
  } else {
    var resultCount = response.Placemark.length; // number of results found by google
    var coordStr = ""; // passed to the batch-coordinate lookup servlet
    
    // initialize the start arrays
    fp_tgGeocodeStartAddrs_ = new Array(resultCount);
    fp_tgGeocodeStartLatLngs_ = new Array(resultCount);
    fp_tgGeocodeStartEncodings_ = new Array(resultCount); // not populated until after the batch-coords query
    
    // iterate through the returned locations, populating the Addr and LatLng arrays
    for(var i = 0; i < resultCount; i++) {
      var place = response.Placemark[i];
      fp_tgGeocodeStartAddrs_[i] = place.address;
      fp_tgGeocodeStartLatLngs_[i] = new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
      coordStr += place.Point.coordinates[0]+","+place.Point.coordinates[1]+(i == resultCount-1 ? "" : ";");
    }
    
    // start the batch coordinate server query
    fp_ajaxLoadAsXML("fp_trpact_batchcoord.php", fp_tgHandleBatchStartResolutionResponse, "coords="+coordStr); 
  }

}

/**
 * fp_tgHandleBatchStartResolutionResponse()
 *
 * Callback function for the AJAX-based batch resolution query for start 
 * locations. Takes an xmlDocument object representing the XML-based response
 * generated by the batch coordinate resolution query. This response consists of
 * a list of 5P-compatible location encodings, one corresponding to each 
 * original coordinate (blank if the location could not be resolved).
 *
 * -- parameters --
 * xmlDoc: the XML-based response 
 */
function fp_tgHandleBatchStartResolutionResponse(xmlDoc) {

  var node = xmlDoc.documentElement;
  if(node.nodeName != "locations") {
    alert('There was a problem with the batch start-location resolution query');
    return;
  }

  var arrIndex = 0;
  var resolvedCount = 0; // the number of locations successfully resolved by 5P-Armour

  // process results, populating the encoded locations array
  for (var i = 0; i < node.childNodes.length; i++) {
    var cnode = node.childNodes.item(i);
    if(cnode.nodeName=="loc") {
      var encoding = cnode.getAttribute("enc");
      fp_dbg("enc="+encoding);
      fp_tgGeocodeStartEncodings_[arrIndex] = encoding;
      if(encoding.length > 0) resolvedCount++; // an empty encoding means the location was not resolved
      arrIndex++;
    }
  }

  if(resolvedCount > 1) // if multiple found, show as onscreen list
    fp_tgShowStartAddresses(); 
  else if(resolvedCount == 1) // if exactly one found, automatically select it
    fp_startLocSelFromGeocode(0); 
  else // otherwise, inform user that no locations were resolved
    alert("Could not resolve start address"); 
}


/**
 * fp_tgShowStartAddresses()
 *
 * Displays the list of successfully resolved start location candidates in the
 * output area of the "Locations" tab for the user to select from. Only called
 * if multiple locations are returned from a geocode query.
 */
function fp_tgShowStartAddresses() {
  // generate HTML containing a list of successfully resolved locations
  var html = "";
  html += "<b>Start location candidates:</b>";
  html += "<div class='fp_tgLocsInnerDiv'>";
  var dispNumber = 1;
  for(var i = 0; i < fp_tgGeocodeStartAddrs_.length; i++) {
    // only add row to display if location was resolved:
    if(fp_tgGeocodeStartEncodings_[i].length > 0) {
      html += "<div class='fp_tgLocRow'>";
      html += "<div class='fp_tgLocLeft'>"+dispNumber+"</div>"
      html += "<div class='fp_tgLocRight'><a href='javascript:fp_startLocSelFromGeocode("+i+")'>"+fp_tgGeocodeStartAddrs_[i]+"</a></div>"
      html += "</div>";
      dispNumber++;
    }
  }
  html += "</div>";

  // create a div containing the above HTML and append it to the left side of
  // the "Locations" output area within the TRP module interface 
  var startDiv = document.createElement("div");
  startDiv.id = "fp_tgStartLocs";
  startDiv.innerHTML = html;
  fp_outputDivs_[FP_OUTPUT_LOCATIONS].appendChild(startDiv);
  
  fp_oTabSelected(FP_OUTPUT_LOCATIONS);
}


//////////////////////// END LOCATION GEOCODE FUNCTIONS ////////////////////////

/**
 * fp_tgHandleGeocodeEndResponse()
 *
 * The callback function passed to the GClientGeocoder object's getLocations() 
 * function. It parses and processes any found end location candidates. 
 *
 * -- parameters --
 * response: the response sent from the GClientGeocoder object 
 */
function fp_tgHandleGeocodeEndResponse(response) {
  if (!response || response.Status.code != 200) {
    alert("Could not resolve end address");
  } else {
    var resultCount = response.Placemark.length; // number of results found by google
    var coordStr = ""; // passed to the batch-coordinate lookup servlet
    
    // initialize the end arrays
    fp_tgGeocodeEndAddrs_ = new Array(resultCount);
    fp_tgGeocodeEndLatLngs_ = new Array(resultCount);
    fp_tgGeocodeEndEncodings_ = new Array(resultCount); // not populated until after the batch-coords query
    
    // iterate through the returned locations, populating the Addr and LatLng arrays
    for(var i = 0; i < resultCount; i++) {
      var place = response.Placemark[i];
      fp_tgGeocodeEndAddrs_[i] = place.address;
      fp_tgGeocodeEndLatLngs_[i] = new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
      coordStr += place.Point.coordinates[0]+","+place.Point.coordinates[1]+(i == resultCount-1 ? "" : ";");
    }
    
    // start the batch coordinate server query
    fp_ajaxLoadAsXML("fp_trpact_batchcoord.php", fp_tgHandleBatchEndResolutionResponse, "coords="+coordStr); 
  }

}

/**
 * fp_tgHandleBatchEndResolutionResponse()
 *
 * Callback function for the AJAX-based batch resolution query for end 
 * locations. Takes an xmlDocument object representing the XML-based response
 * generated by the batch coordinate resolution query. This response consists of
 * a list of 5P-compatible location encodings, one corresponding to each 
 * original coordinate (blank if the location could not be resolved).
 *
 * -- parameters --
 * xmlDoc: the XML-based response 
 */
function fp_tgHandleBatchEndResolutionResponse(xmlDoc) {

  var node = xmlDoc.documentElement;
  if(node.nodeName != "locations") {
    alert('There was a problem with the batch end-location resolution query');
    return;
  }

  var arrIndex = 0;
  var resolvedCount = 0; // the number of locations successfully resolved by 5P-Armour

  // process results, populating the encoded locations array
  for (var i = 0; i < node.childNodes.length; i++) {
    var cnode = node.childNodes.item(i);
    if(cnode.nodeName=="loc") {
      var encoding = cnode.getAttribute("enc");
      fp_dbg("enc="+encoding);
      fp_tgGeocodeEndEncodings_[arrIndex] = encoding;
      if(encoding.length > 0) resolvedCount++; // an empty encoding means the location was not resolved
      arrIndex++;
    }
  }

  if(resolvedCount > 1) // if multiple found, show as onscreen list
    fp_tgShowEndAddresses(); 
  else if(resolvedCount == 1) // if exactly one found, automatically select it
    fp_endLocSelFromGeocode(0); 
  else // otherwise, inform user that no locations were resolved
    alert("Could not resolve end address"); 
}


/**
 * fp_tgShowEndAddresses()
 *
 * Displays the list of successfully resolved end location candidates in the
 * output area of the "Locations" tab for the user to select from. Only called
 * if multiple locations are returned from a geocode query.
 */
function fp_tgShowEndAddresses() {
  // generate HTML containing a list of successfully resolved locations
  var html = "";
  html += "<b>End location candidates:</b>";
  html += "<div class='fp_tgLocsInnerDiv'>";
  var dispNumber = 1;
  for(var i = 0; i < fp_tgGeocodeEndAddrs_.length; i++) {
    // only add row to display if location was resolved:
    if(fp_tgGeocodeEndEncodings_[i].length > 0) {
      html += "<div class='fp_tgLocRow'>";
      html += "<div class='fp_tgLocLeft'>"+dispNumber+"</div>"
      html += "<div class='fp_tgLocRight'><a href='javascript:fp_endLocSelFromGeocode("+i+")'>"+fp_tgGeocodeEndAddrs_[i]+"</a></div>"
      html += "</div>";
      dispNumber++;
    }
  }
  html += "</div>";

  // create a div containing the above HTML and append it to the left side of
  // the "Locations" output area within the TRP module interface 
  var endDiv = document.createElement("div");
  endDiv.id = "fp_tgEndLocs";
  endDiv.innerHTML = html;
  fp_outputDivs_[FP_OUTPUT_LOCATIONS].appendChild(endDiv);
  
  fp_oTabSelected(FP_OUTPUT_LOCATIONS);
}


/*function fp_tgHandleGeocodeEndResponse(response) {
  if (!response || response.Status.code != 200) {
    alert("Could not resolve end address");
  } else {
    fp_tgGeocodeEndAddrs_ = new Array(response.Placemark.length);
    fp_tgGeocodeEndLatLngs_ = new Array(response.Placemark.length);
    for(var i = 0; i < response.Placemark.length; i++) {
      var place = response.Placemark[i];
      fp_tgGeocodeEndAddrs_[i] = place.address;
      fp_tgGeocodeEndLatLngs_[i] = new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
    }
    fp_dbg("response count: "+response.Placemark.length);
    fp_tgShowEndAddresses();
  }
}

function fp_tgShowEndAddresses() {
  var html = "";
  
  html += "<b>End location candidates:</b>";
  html += "<div class='fp_tgLocsInnerDiv'>";
  for(var i = 0; i < fp_tgGeocodeEndAddrs_.length; i++) {
    html += "<div class='fp_tgLocRow'>";
    html += "<div class='fp_tgLocLeft'>"+(i+1)+"</div>"
    html += "<div class='fp_tgLocRight'><a href='javascript:fp_endLocSelFromGeocode("+i+")'>"+fp_tgGeocodeEndAddrs_[i]+"</a></div>"
    html += "</div>";
  }
  html += "</div>";

  var endDiv = document.createElement("div");
  endDiv.id = "fp_tgEndLocs";
  endDiv.innerHTML = html;
   
  var output = fp_outputDivs_[FP_OUTPUT_LOCATIONS];
  output.appendChild(endDiv);
  
  fp_oTabSelected(FP_OUTPUT_LOCATIONS);
}*/