# Source: open-layers/ol-geocoder.js

    /**
     * @namespace WPGMZA
     * @module OLGeocoder
     * @requires WPGMZA.Geocoder
     */
    (function($) {

    	/**
    	 * @class OLGeocoder
    	 * @extends Geocoder
    	 * @summary OpenLayers geocoder - uses Nominatim by default
    	 */
    	WPGMZA.OLGeocoder = function()
    	{

    	}

    	WPGMZA.OLGeocoder.prototype = Object.create(WPGMZA.Geocoder.prototype);
    	WPGMZA.OLGeocoder.prototype.constructor = WPGMZA.OLGeocoder;

    	/**
    	 * @function getResponseFromCache
    	 * @access protected
    	 * @summary Tries to retrieve cached coordinates from server cache
    	 * @param {string} address The street address to geocode
    	 * @param {function} callback Where to send the results, as an array
    	 * @return {void}
    	 */
    	WPGMZA.OLGeocoder.prototype.getResponseFromCache = function(address, callback)
    	{
    		$.ajax(WPGMZA.ajaxurl, {
    			data: {
    				action: "wpgmza_query_nominatim_cache",
    				query: address
    			},
    			success: function(response, xhr, status) {
    				callback(response);
    			}
    		});
    	}

    	/**
    	 * @function getResponseFromNominatim
    	 * @access protected
    	 * @summary Queries Nominatim on the specified address
    	 * @param {object} options An object containing the options for geocoding, address is a mandatory field
    	 * @param {function} callback The function to send the results to, as an array
    	 */
    	WPGMZA.OLGeocoder.prototype.getResponseFromNominatim = function(options, callback)
    	{
    		var data = {
    			q: options.address,
    			format: "json"
    		};

    		if(options.country)
    			data.countrycodes = options.country;

    		$.ajax("https://nominatim.openstreetmap.org/search/", {
    			data: data,
    			success: function(response, xhr, status) {
    				callback(response);
    			},
    			error: function(response, xhr, status) {
    				callback(null, WPGMZA.Geocoder.FAIL)
    			}
    		});
    	}

    	/**
    	 * @function cacheResponse
    	 * @access protected
    	 * @summary Caches a response on the server, usually after it's been returned from Nominatim
    	 * @param {string} address The street address
    	 * @param {object|array} response The response to cache
    	 * @returns {void}
    	 */
    	WPGMZA.OLGeocoder.prototype.cacheResponse = function(address, response)
    	{
    		$.ajax(WPGMZA.ajaxurl, {
    			data: {
    				action: "wpgmza_store_nominatim_cache",
    				query: address,
    				response: JSON.stringify(response)
    			},
    			method: "POST"
    		});
    	}

    	/**
    	 * @function getLatLngFromAddress
    	 * @access public
    	 * @summary Attempts to geocode an address, firstly by checking the cache for previous
    	 * results, if this fails the Nominatim server will be queried, cached and sent to the
    	 * specified callback
    	 * @param {object} options An object containing the options for geocoding, address is a mandatory field
    	 * @param {function} callback The function to send the results to, as an array
    	 * @returns {void}
    	 */
    	WPGMZA.OLGeocoder.prototype.getLatLngFromAddress = function(options, callback)
    	{
    		var self = this;
    		var address = options.address;

    		var latLng;
    		if(latLng = WPGMZA.isLatLngString(address))
    			return WPGMZA.Geocoder.prototype.getLatLngFromAddress.call(this, options, callback);

    		function finish(response, status)
    		{
    			for(var i = 0; i < response.length; i++)
    			{
    				response[i].geometry = {
    					location: new WPGMZA.LatLng({
    						lat: parseFloat(response[i].lat),
    						lng: parseFloat(response[i].lon)
    					})
    				};

    				response[i].lat = parseFloat(response[i].lat);
    				response[i].lng = parseFloat(response[i].lon);
    			}

    			callback(response, status);
    		}

    		this.getResponseFromCache(address, function(response) {
    			if(response.length)
    			{
    				finish(response, WPGMZA.Geocoder.SUCCESS);
    				return;
    			}

    			self.getResponseFromNominatim(options, function(response, status) {
    				if(status == WPGMZA.Geocoder.FAIL)
    				{
    					callback(null, WPGMZA.Geocoder.FAIL);
    					return;
    				}

    				if(response.length == 0)
    				{
    					callback(response, WPGMZA.Geocoder.ZERO_RESULTS);
    					return;
    				}

    				finish(response, WPGMZA.Geocoder.SUCCESS);

    				self.cacheResponse(address, response);
    			});
    		});
    	}

    })(jQuery);