
/******************************************************************************/
/**                                                                          **/
/**                         Map handling functions                           **/
/**                                                                          **/

// item list and item form maps are Google Maps V3, the directions map is
// Google Maps V2
(function($){

// constructor (must be before the public functions) ---------------------------

// do not call the namespace 'map' because it crashes with the jQuery map
// data structure
jQuery.mapFunctions = {
    map: null,
    geocoder: null,
    infowindow: null,
    map2: null,
    gdir: null,
    marker: null,
    zoom: {
        countryLarge: 5,
        country: 6,
        province: 10,
        zone: 13,
        address: 15
    },
    // Madrid's latitude and longitude as default
    defaultLatitude: 40.4167404,
    defaultLongitude: -3.7032497
};

//------------------------------------------------------------------------------

jQuery.mapFunctions.initializeMapItemList = function(
    containerDiv, latitude, longitude, mapZoom)
{

  // the geocoder is not initialized here but in the getLatLngAndSubmitSearch()
  // function, where it is first required, because the map may not be
  // initialized but the geocoder needed for a search
//  $.mapFunctions.geocoder = new google.maps.Geocoder();

  if (( ! latitude) || ( ! longitude)) {
    latitude = $.mapFunctions.defaultLatitude;
    longitude = $.mapFunctions.defaultLongitude;
    mapZoom = $.mapFunctions.zoom.country;
  }

  var latLng = new google.maps.LatLng(latitude, longitude);

  var mapOptions = {
    zoom: mapZoom,
    center: latLng,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    scrollwheel: false
  }

  $.mapFunctions.map = new google.maps.Map(containerDiv, mapOptions);
  
//  if (mapZoom == $.mapFunctions.zoom.zone) {
//    var marker = new google.maps.Marker({
//        draggable: true,
//        icon: $.globalFunctions.getImageUrl('markerUser'),
//        position: latLng,
//        map: $.mapFunctions.map,
//        title: name // title = tooltip
//    });
//
//    // the function of the third parameter of addListener must be inline.
//    // If it is detached, it doesn't work.
//    google.maps.event.addListener(marker, 'click', function() {
//        $.mapFunctions.infowindow.setContent($.messages.altTitleCaption.userMarker);
//        $.mapFunctions.infowindow.open($.mapFunctions.map, marker);
//    });
//
//  }
  
  $.mapFunctions.infowindow = new google.maps.InfoWindow();
  
  google.maps.event.addListener($.mapFunctions.map, 'click', function() {
    $.mapFunctions.infowindow.close();
  });
};

//------------------------------------------------------------------------------
/**
* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
*/
jQuery.mapFunctions.initializeMapItemForm = function(containerDiv, latitude, longitude, marker) {

  $.mapFunctions.geocoder = new google.maps.Geocoder();

  var mapZoom = $.mapFunctions.zoom.address;

  if (( ! latitude) || ( ! longitude)) {
    latitude = $.mapFunctions.defaultLatitude;
    longitude = $.mapFunctions.defaultLongitude;
    mapZoom = $.mapFunctions.zoom.countryLarge;
  }

  var latLng = new google.maps.LatLng(latitude, longitude);

  var mapOptions = {
    zoom: mapZoom,
    center: latLng,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    scrollwheel: false,
    mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
//    navigationControlOptions: {style: google.maps.NavigationControlStyle.ZOOM_PAN}
    navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL}
  }
  $.mapFunctions.map = new google.maps.Map(containerDiv, mapOptions);

  $.mapFunctions.marker = new google.maps.Marker({
    icon: $.globalFunctions.getImageUrl('marker'),
    cursor: 'default'
  });

//  if (mapZoom == $.mapFunctions.zoom.address) {
  if (marker) {
    $.mapFunctions.marker.setPosition(latLng);
    $.mapFunctions.marker.setMap($.mapFunctions.map);
  }
};

//------------------------------------------------------------------------------

jQuery.mapFunctions.countryZoomMapItemForm = function() {

    if ($.mapFunctions.map) {
        var latLng = new google.maps.LatLng(
            $.mapFunctions.defaultLatitude,
            $.mapFunctions.defaultLongitude
        );

        $.mapFunctions.map.setCenter(latLng);
        $.mapFunctions.map.setZoom($.mapFunctions.zoom.countryLarge);

        $.mapFunctions.marker.setMap(null);
    }
};

//------------------------------------------------------------------------------
// the directions map is Google Maps V2
jQuery.mapFunctions.initializeDirectionsMap = function(
    divMap, divDirections, latitude, longitude, marker)
{

  if (GBrowserIsCompatible()) {
    var zoom = $.mapFunctions.zoom.address;
    if (( ! latitude) || ( ! longitude)) {
      latitude = $.mapFunctions.defaultLatitude;
      longitude = $.mapFunctions.defaultLongitude;
      zoom = $.mapFunctions.zoom.countryLarge;
    }

    var latLng = new GLatLng(latitude, longitude);
    $.mapFunctions.map2 = new GMap2(divMap);
    $.mapFunctions.map2.setCenter(latLng, zoom);
    $.mapFunctions.map2.disableScrollWheelZoom();
    $.mapFunctions.map2.addMapType(G_PHYSICAL_MAP);
    $.mapFunctions.map2.addControl(new GMenuMapTypeControl());
    $.mapFunctions.map2.addControl(new GSmallZoomControl3D());
//    $.mapFunctions.map2.addControl(new GLargeMapControl());
    
    var icon = new GIcon(G_DEFAULT_ICON);
    if (marker) {
        icon.image = $.globalFunctions.getImageUrl('marker');
        icon.iconSize = new GSize(24, 50);
        icon.iconAnchor = new GPoint(10, 50);
    }
    else {
        icon.image = $.globalFunctions.getImageUrl('markerAproxLarge');
        icon.iconSize = new GSize(400, 400);
        icon.iconAnchor = new GPoint(200, 200);
    }
    icon.shadowSize = new GSize(0, 0);
    
    var markerOptions = {
        icon: icon,
        draggable: true
    };
    $.mapFunctions.map2.addOverlay(new GMarker(latLng, markerOptions));
    
    $.mapFunctions.gdir = new GDirections($.mapFunctions.map2, divDirections);
    // IE fails if a non existent function is assigned to an event
//     GEvent.addListener(gdir, "load", onGDirectionsLoad);
    GEvent.addListener($.mapFunctions.gdir, "error", $.mapFunctions.handleErrors);
  }
};

//------------------------------------------------------------------------------
/**
 * Write an html row with the latitude and longitude of a given address. The
 * row is written in a table called "provinceGeolocations" of an iframe called
 * "frameResult".
 *
 * This function is called by a cache geolocation function.
 *
 * @param address string
 */
jQuery.mapFunctions.getLatitudeLongitudeRow = function(address) {

  address = decodeURIComponent(address);

  // the function of the second parameter of the "geocode" function must be
  // inline. If it is detached, it doesn't work. This function must get
  // exactly two specific parameters. The variable "map" must be global
  $.mapFunctions.geocoder.geocode( {address: address}, function(results, status) {

    var settings = {
        scrollToTop: false,
        title: $.messages.dialog.titles.notFound,
        message: $.messages.dialog.messages.addressNotFound + address,
        buttons: $.configuration.dialog.buttons.ok
    };

    if (status == google.maps.GeocoderStatus.OK && results.length) {
      // it must be checked always that a result was returned, as it is
      // possible to return an empty results object
      if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
          
        var provinceGeolocationRow = '<tr><td>' + address + '</td><td>'
                                   + results[0].geometry.location.lat() + '</td><td>'
                                   + results[0].geometry.location.lng() + '</td></tr>';

        $('#frameResult').contents().find('#provinceGeolocations').append(provinceGeolocationRow);

      }
      else {
        $.globalFunctions.dialogOpen(settings);
      }
    }
    else {
      $.globalFunctions.dialogOpen(settings);
    }
  });
};

//------------------------------------------------------------------------------

jQuery.mapFunctions.setLatLngAndSubmitSearch = function(location) {

    $('#address').attr('geolocated', 'true');

    $('#latitude').val(location.lat());
    $('#longitude').val(location.lng());

//    $.globalFunctions.submitSearch();
    $.searchPanel.submitSearch();
}

//------------------------------------------------------------------------------

jQuery.mapFunctions.getLatLngAndSubmitSearch = function(address) {

  address = decodeURIComponent(address);
  
//  $('#address').attr('geolocated', 'false');
  $('#address').removeAttr('geolocated');

  $.mapFunctions.geocoder = new google.maps.Geocoder();

  // the function of the second parameter of the "geocode" function must be
  // inline. If it is detached, it doesn't work. This function must get
  // exactly two specific parameters. The variable "map" must be global
  $.mapFunctions.geocoder.geocode( {address: address}, function(results, status) {

    var settings = {
        scrollToTop: false,
        title: $.messages.dialog.titles.notFound,
        message: $.messages.dialog.messages.addressNotFound + address,
        buttons: $.configuration.dialog.buttons.ok
    };

    if (status == google.maps.GeocoderStatus.OK && results.length) {
      // it must always be checked that a result was returned, as it is
      // possible to return an empty results object
      if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
          if (results.length == 1) {
              jQuery.mapFunctions.setLatLngAndSubmitSearch(results[0].geometry.location);
          }
          else {
              $.mapFunctions.multipleResults(address, results);
          }
      }
      else {
        $.globalFunctions.dialogOpen(settings);
      }
    }
    else {
        $.globalFunctions.dialogOpen(settings);
    }
  });
};

//------------------------------------------------------------------------------
// the directions map is Google Maps V2
jQuery.mapFunctions.setLatLngForDirectionsMap = function(location) {

    var $address = $('.itemDisplay .address');

    $address.removeAttr('geolocate');

    $.mapFunctions.initializeDirectionsMap(
        $("#divMapDisplay").get(0),
        $("#divDirections").get(0),
//            $('#latitudeDisplay').sanitizedValue(),
//            $('#longitudeDisplay').sanitizedValue(),
//            $('#markerDisplay').sanitizedValue()
        location.lat(),
        location.lng(),
        $address.find('.marker').sanitizedValue()
    );
}

//------------------------------------------------------------------------------
// the directions map is Google Maps V2
jQuery.mapFunctions.getLatLngForDirectionsMap = function(address) {

  address = decodeURIComponent(address);

  $.mapFunctions.geocoder = new GClientGeocoder();
  
  $.mapFunctions.geocoder.getLatLng(address, function(point) {

    if (point) {
        jQuery.mapFunctions.setLatLngForDirectionsMap(point);
    }
    else {

        var settings = {
            scrollToTop: false,
            title: $.messages.dialog.titles.notFound,
            message: $.messages.dialog.messages.addressNotFound + address,
            buttons: $.configuration.dialog.buttons.ok
        };

        $.globalFunctions.dialogOpen(settings);
    }
  });
};

//------------------------------------------------------------------------------
/**
 * Display a dialog with the multiple results found, so that the user can
 * choose one of them.
 *
 * @param address string
 * @param results Google Maps results.
 */
jQuery.mapFunctions.multipleResults = function(address, results) {

    var resultAddresses = '<ul class="multipleResults">';

    for (var i = 0; i < results.length; i++) {
        resultAddresses += '<li index="' + i + '">'
                         + results[i].formatted_address
                         + '</li>';
    }
    
    resultAddresses += '</ul>';

    var message = $.messages.dialog.messages.multipleResults.replace('%s', address)
                + resultAddresses;

    var settings = {
        scrollToTop: false,
        title: $.messages.dialog.titles.multipleResults,
        message: message,
        buttons: $.configuration.dialog.buttons.cancel,
        width: 430
    };

    $.globalFunctions.dialogOpen(settings);

    $('.multipleResults li').click( function() {
        jQuery.mapFunctions.setLatLngAndSubmitSearch(
            results[$(this).attr('index')].geometry.location
        );
    });
};

//------------------------------------------------------------------------------
/**
 * Set a marker in a map that displays some given information when clicked.
 *
 * @param latitude float
 * @param longitude float
 * @param name string
 * @param information string May be html.
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 */
jQuery.mapFunctions.setMarkerLatLng = function(latitude, longitude, aprox, title, information) {

  if (( ! latitude) || ( ! longitude)) {
    latitude = $.mapFunctions.defaultLatitude;
    longitude = $.mapFunctions.defaultLongitude;
  }

  var icon = 'marker';
  if (aprox) {
      icon = 'markerAprox';
  }
  var marker = new google.maps.Marker({
      draggable: true,
      icon: $.globalFunctions.getImageUrl(icon),
      position: new google.maps.LatLng(latitude, longitude),
      map: $.mapFunctions.map,
      title: title // title = tooltip
  });

  // the function of the third parameter of addListener must be inline.
  // If it is detached, it doesn't work. 
  google.maps.event.addListener(marker, 'click', function() {
    $.mapFunctions.infowindow.setContent(decodeURIComponent(information));
    $.mapFunctions.infowindow.open($.mapFunctions.map, marker);
  });
  
  return marker;
};

//------------------------------------------------------------------------------

// the "setMarkerMapList" and "setMarkerMapForm" functions cannot be unified,
// because of the inline function parameter of the "geocode" function, which
// cannot be detached
jQuery.mapFunctions.setMarkerMapForm = function(address, marker) {
  
  $.mapFunctions.marker.setMap(null);
  $('#latitude').val('');
  $('#longitude').val('');

  address = $.trim(decodeURIComponent(address))

  if (address) {
      // the function of the second parameter of the "geocode" function must be
      // inline. If it is detached, it doesn't work. This function must get
      // exactly two specific parameters. The variable "map" must be global
      $.mapFunctions.geocoder.geocode( {address: address}, function(resultsMapForm, statusMapForm) {
        if (statusMapForm == google.maps.GeocoderStatus.OK && resultsMapForm.length) {
          // it must be checked always that a result was returned, as it is
          // possible to return an empty results object
          if (statusMapForm != google.maps.GeocoderStatus.ZERO_RESULTS) {

            $.mapFunctions.setMarkerMapFormLatLng(
                resultsMapForm[0].geometry.location.lat(),
                resultsMapForm[0].geometry.location.lng(),
                resultsMapForm[0].geometry.location,
                marker
            );
          }
        }
        else {
            var settings = {
                scrollToTop: false,
                title: $.messages.dialog.titles.notFound,
                message: $.messages.dialog.messages.addressNotFound + address,
                buttons: $.configuration.dialog.buttons.ok
            };
            $.globalFunctions.dialogOpen(settings);
        }
      });
  }
};

//------------------------------------------------------------------------------

/**
 * @param latitude float
 * @param longitude float
 * @param latLng google.maps.LatLng May not be passed. If not passed, a new
 *               object is created from the other two parameters, latitude and
 *               longitude.
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 */
jQuery.mapFunctions.setMarkerMapFormLatLng = function(latitude, longitude, latLng, marker) {

    var mapZoom = $.mapFunctions.zoom.address;

    if (( ! latitude) || ( ! longitude)) {
        latitude = $.mapFunctions.defaultLatitude;
        longitude = $.mapFunctions.defaultLongitude;
        mapZoom = $.mapFunctions.zoom.countryLarge;
    }

    if ( ! latLng) {
        latLng = new google.maps.LatLng(latitude, longitude);
    }

    $.mapFunctions.map.setCenter(latLng);
    $.mapFunctions.map.setZoom(mapZoom);

    if (mapZoom == $.mapFunctions.zoom.countryLarge) {
        $.mapFunctions.marker.setMap(null);
    }
    else {
        if (marker) {
            $.mapFunctions.marker.setPosition(latLng);
            $.mapFunctions.marker.setMap($.mapFunctions.map);
        }
        
        $('#latitude').val(latitude);
        $('#longitude').val(longitude);
    }

};

//------------------------------------------------------------------------------

jQuery.mapFunctions.setDirections = function(fromAddress, toAddress, locale) {
  fromAddress = decodeURIComponent(fromAddress);
  toAddress = decodeURIComponent(toAddress);
  if (fromAddress && toAddress) {
    $.mapFunctions.gdir.load('from: ' + fromAddress + ' to: ' + toAddress, { 'locale': locale });
  }
};

//------------------------------------------------------------------------------

jQuery.mapFunctions.handleErrors = function(){
  var settings = {
    scrollToTop: false,
    title: $.messages.dialog.titles.unknownError,
    message: $.messages.dialog.messages.unknownError,
    buttons: $.configuration.dialog.buttons.ok,
    width: 470
  };
  if ($.mapFunctions.gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS) {
//     "Error: " + gdir.getStatus().code;
    settings.title = $.messages.dialog.titles.unknownAddress;
    settings.message = $.messages.dialog.messages.unknownAddress;
  }
  else if ($.mapFunctions.gdir.getStatus().code == G_GEO_SERVER_ERROR) {
    settings.title = $.messages.dialog.titles.serverError;
    settings.message = $.messages.dialog.messages.serverError;
  }
  else if ($.mapFunctions.gdir.getStatus().code == G_GEO_MISSING_QUERY) {
    settings.title = $.messages.dialog.titles.missingQuery;
    settings.message = $.messages.dialog.messages.missingQuery;
  }
  //   else if (gdir.getStatus().code == G_UNAVAILABLE_ADDRESS)  <--- Doc bug... this is either not defined, or Doc is wrong
  //     alert("The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons.\n Error code: " + gdir.getStatus().code);
  else if ($.mapFunctions.gdir.getStatus().code == G_GEO_BAD_KEY) {
    settings.title = $.messages.dialog.titles.badKey;
    settings.message = $.messages.dialog.messages.badKey;
  }
  else if ($.mapFunctions.gdir.getStatus().code == G_GEO_BAD_REQUEST) {
    settings.title = $.messages.dialog.titles.badRequest;
    settings.message = $.messages.dialog.messages.badRequest;
  }
  $.globalFunctions.dialogOpen(settings);
};

//------------------------------------------------------------------------------

jQuery.mapFunctions.centerMap = function(latitude, longitude) {

  if (( ! latitude) || ( ! longitude)) {
    latitude = $.mapFunctions.defaultLatitude;
    longitude = $.mapFunctions.defaultLongitude;
//    mapZoom = $.mapFunctions.zoom.country;
  }

  var latLng = new google.maps.LatLng(latitude, longitude);
  
  $.mapFunctions.map.setCenter(latLng);
  
  $.mapFunctions.map.setZoom($.mapFunctions.zoom.address);
};

//------------------------------------------------------------------------------

})(jQuery);

/**                                                                          **/
/**                         Map handling functions                           **/
/**                                                                          **/
/******************************************************************************/

