var famGoogleMap = null;
window.fundament = window.fundament || {};
fundament.ec = fundament.ec || {};
fundament.ec.google = fundament.ec.google || {};

(function($)
{
   fundament.ec.google.theMap = null;
   var latitudeNL = 52.2;
   var longitudeNL = 5.3;

   function _getDefaultOptions()
   {
      return {
         zoom: 7,
         center: new google.maps.LatLng(latitudeNL, longitudeNL),
         mapTypeId: google.maps.MapTypeId.TERRAIN,
         mapTypeControl: true,
         mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
         navigationControl: true,
         navigationControlOptions: {style: google.maps.NavigationControlStyle.ZOOM_PAN}
      };
   }

   function _getFixedOnHollandOptions()
   {
      return {
         center: new google.maps.LatLng(latitudeNL, longitudeNL),
         disableDefaultUI: true,
         disableDoubleClickZoom: true,
         draggable: false,
         keyboardShortcuts: false,
         mapTypeId: google.maps.MapTypeId.TERRAIN,
         scrollwheel: false,
         zoom: 7
      };
   }

   /** Get Google Maps LatLng instance for 'center of the Netherlands' **/
   fundament.ec.google.getLatLngNetherlands = function()
   {
      return new google.maps.LatLng(latitudeNL, longitudeNL);
   };
   fundament.ec.google.placedMarkers = new Array();
   fundament.ec.google.addMarker = function(marker)
   {
      this.placedMarkers[this.placedMarkers.length] = marker;
   };


   fundament.ec.google.loadGoogleMap = function (mapOptions)
   {
      var mapOptionsToUse = _getDefaultOptions();
      if (mapOptions)
      {
         mapOptionsToUse = mapOptions;
      }
      fundament.ec.google.theMap = new google.maps.Map(document.getElementById("ECMapCanvas"), mapOptionsToUse);
      famGoogleMap = fundament.ec.google.theMap;
   };

   /** Load a map fixed on the Netherlands, optionally override some of these map options**/
   fundament.ec.google.loadGoogleMapFixedOnHolland = function (mapOptions)
   {
      var combinedOptions = jQuery.extend({}, _getFixedOnHollandOptions(), mapOptions);
      fundament.ec.google.loadGoogleMap(combinedOptions);
   };

   fundament.ec.google.getECGoogleMap = function ()
   {
      return fundament.ec.google.theMap;
   };

   fundament.ec.google.print = function ()
   {
      window.open(printurl);
   };

   /**
    *
    * @param _paramMap a map object containing extra optional parmas for this function.
    *       - location: a google LatLng object, it will place a marker at this position on the map, the param has
    *                   precedence over the latitude / longitude params.
    *       - latitude: a latitude value, if a longitude is specified it will place a marker at these positions on the map.
    *       - longitude: a longitude value, if a latitude is specified it will place a marker at these positions on the map.
    */
   fundament.ec.google.placeMarkerOnMap = function(paramMap)
   {
      var params =
      {
         clearMarkers: false,
         icon: null,
         latitude: null,
         location: null,
         longitude: null,
         title: null
      };
      $.extend(params,paramMap);
      if (!params.location)
      {
         if (params.latitude && params.longitude)
         {
            params.location = new google.maps.LatLng(params.latitude, params.longitude);
         }
      }

      if (params.location)
      {
         //clear previous markers
         if (params.clearMarkers)
         {
            for (var im = 0; im < fundament.ec.google.placedMarkers.length; im++)
            {
               var markerToDelete = fundament.ec.google.placedMarkers[im];
               markerToDelete.setMap(null);
               var delIndex = fundament.ec.google.placedMarkers.indexOf(markerToDelete);
               if (delIndex > -1)
               {
                  fundament.ec.google.placedMarkers.splice(delIndex, 1);
               }
            }
         }
         var marker = new google.maps.Marker({
            map: fundament.ec.google.getECGoogleMap(),
            position: params.location,
            title: params.title,
            icon: params.icon
         });
         fundament.ec.google.addMarker(marker);
      }
   };

   /**
    * Returns the city name present in the geocoder response.
    * @param googleGeocoderResponse see also http://code.google.com/apis/maps/documentation/v3/reference.html#GeocoderResponse.
    */
   fundament.ec.google.getCityName = function(googleGeocoderResponse)
   {
      var addressComponents = googleGeocoderResponse.address_components;
      var sublocality;
      var locality;
      var cityName;
      // check if the address components contains a sublocality or locality
      for (var iac = 0; iac < addressComponents.length; iac++)
      {
         var addressComponentTypes = addressComponents[iac].types;
         for (var i = 0; i < addressComponentTypes.length; i++)
         {
            var componentType = addressComponentTypes[i];
            if (componentType === "sublocality")
            {
               sublocality = addressComponents[iac].short_name;
            }
            if (componentType === "locality")
            {
               locality = addressComponents[iac].short_name;
            }
         }
      }
      // if a sublocality was found use this value as it's city name
      if (sublocality)
      {
         cityName = sublocality;
      }
      // otherwise if a locality was found use this value as it's city name
      else if (locality)
      {
         cityName = locality;
      }
      return cityName;
   };


   /**
    * Returns only the location results of the google geocoder result (establisment, etc. are filtered out)
    * @param googleGeocoderResults see also http://code.google.com/apis/maps/documentation/v3/reference.html#GeocoderResponse.
    */
   fundament.ec.google.filterLocations = function(googleGeocoderResults)
   {
      locations = []
      for (var i=0; i < googleGeocoderResults.length; i++)
      {
         result = googleGeocoderResults[i];
         locationAdded = false;
         var types = result.types;
         for (var it = 0; it < types.length; it++)
         {
            var type = types[it];
            if (!locationAdded && type === "locality")
            {
               locations[i] = result;
               locationAdded = true;
            }
         }
      }
      return locations;
   }

   /**
    *
    * @param addressId a html id of the element containing the address to lookup
    * @param paramMap a map object containing extra optional parmas for this function.
    *       - feedbackId: a html id of the element where to display the search result
    *       - defaultAddressSuffix: if specified this will be added as a suffix to the address
    *       - latResultInput: a html id of the element where to place the latitude result
    *       - lngResultInput: a html id of the element where to place the longitude result
    *       - displayOnMap: if set to true it will place a marker on the map indicating the found address
    * @TODO use google regions instead of the defaultAddressSuffix
    */
   fundament.ec.google.codeAddress = function (addressId, paramMap)
   {
      var feedbackId = paramMap.feedbackId;
      var cityFeedbackId = paramMap.cityFeedbackId;
      var defaultAddressSuffix = paramMap.defaultAddressSuffix;
      var latResultInput = paramMap.latResultInput;
      var lngResultInput = paramMap.lngResultInput;
      var cityInput = paramMap.cityInput;
      var displayOnMap = paramMap.displayOnMap;
      var centerOnMap = paramMap.centerOnMap;
      var callback = paramMap.callBack;

      var address = document.getElementById(addressId).value;
      var addressExtended = document.getElementById(addressId).value;

      if (defaultAddressSuffix)
      {
         addressExtended = address + " " + defaultAddressSuffix;
      }
      var geocoder = new google.maps.Geocoder();
      if (geocoder)
      {
         geocoder.geocode({ 'address': addressExtended}, function(results, status)
         {
            var feedbackInfo = "";
            if (status == google.maps.GeocoderStatus.OK)
            {
               locations = fundament.ec.google.filterLocations(results);
               if (!locations) 
               {
                  feedbackInfo += "geen locaties gevonden voor '" + address + "'";
               }
               else if (locations.length > 1)
               {
                  feedbackInfo += "Meerdere locaties (" + locations.length + ") gevonden voor '" + address + "', probeer een specifieker addres op te geven.";
                  for (var i = 0; i < locations.length; i++)
                  {
                     feedbackInfo += locations[i].formatted_address + "<br/>";
                     var location = locations[i].geometry.location;
                     feedbackInfo += "latitude:" + location.lat() + "<br/>";
                     feedbackInfo += "longitude:" + location.lng() + "<br/>";
                  }
               }
               else
               {
                  feedbackInfo += locations[0].formatted_address + "<br/>";
                  var locationResult = locations[0].geometry.location;
                  feedbackInfo += "latitude:" + locationResult.lat() + "<br/>";
                  feedbackInfo += "longitude:" + locationResult.lng() + "<br/>";

                  var cityName = fundament.ec.google.getCityName(locations[0]);
                  var cityFeedbackElement = document.getElementById(cityFeedbackId);
                  if (cityFeedbackElement)
                  {
                     cityFeedbackElement.innerHTML = cityName;
                  }
                  feedbackInfo += "plaats:" + cityName + "<br/>";

                  var latitudeElement = document.getElementById(latResultInput);
                  if (latitudeElement)
                  {
                     latitudeElement.value = locationResult.lat();
                  }
                  var longitudeElement = document.getElementById(lngResultInput);
                  if (longitudeElement)
                  {
                     longitudeElement.value = locationResult.lng();
                  }
                  var cityInputElement = document.getElementById(cityInput);
                  if (cityInputElement)
                  {
                     cityInputElement.value = cityName;
                  }
                  if (displayOnMap === true)
                  {
                     fundament.ec.google.placeMarkerOnMap({"location": locations[0].geometry.location, "clearMarkers": true});
                  }
                  if (centerOnMap === true)
                  {
                     fundament.ec.google.theMap.setCenter(locations[0].geometry.location);
                  }
               }
            }
            else if (status == google.maps.GeocoderStatus.ZERO_RESULTS || status == google.maps.GeocoderStatus.INVALID_REQUEST)
            {
               feedbackInfo += "Geen locatie gevonden voor '" + address + "', probeer het opnieuw.";
            }
            else
            {
               feedbackInfo += "Geocode was not successful for the following reason: " + status;
            }
            var feedbackElement = document.getElementById(feedbackId);
            if (feedbackElement)
            {
               feedbackElement.innerHTML = feedbackInfo;
            }
            if (callback())
            {
               callBack();
            }
            ;
         });
      }
   };

})(jQuery);


