/**
* BeNomad BeMap JavaScript API - Geocoder v1.5 extension
*
* Augments the existing `bemap.Geocoder` prototype with a Promise-based
* `geocode(request)` and `revGeocode(request)`. Dispatch is `instanceof`-based,
* so legacy callers passing `{searchInfo, success, failed}` keep their behaviour.
*
* Wire format note: the BeMap v1.5 backend does not expose a dedicated forward
* geocoding endpoint. The closest equivalent is
* `POST service/geocoding/autocomplete/1.0` with `addressDetails: true` — the
* response contains the structured PostalAddress + Coordinate per item, which
* is what `bemap.Geocoder.geocode()` returns. This matches the Flutter SDK's
* decision (no `Geocoder` class exists there — only `Autocomplete` +
* `ReverseGeocoder`).
*
* Reverse geocoding goes through `bemap.ReverseGeocoder` (which posts to
* `service/geocoding/1.0/reverse`).
*
* @since 1.5.0
*/
(function() {
if (typeof bemap === 'undefined' || !bemap.Geocoder) return;
/** @private */
bemap.Geocoder.prototype._v2 = function() {
if (!this._v2Instance) {
this._v2Instance = new bemap.ServiceV2(this.ctx, {});
}
return this._v2Instance;
};
var legacyGeocode = bemap.Geocoder.prototype.geocode;
var legacyRevGeocode = bemap.Geocoder.prototype.revGeocode;
/**
* Geocode a structured or free-text request.
*
* @public
* @param {bemap.GeocodingRequest|Object} request When a `GeocodingRequest`
* is passed the call returns a Promise. Any other shape falls through to
* the legacy callback-style implementation.
* @param {Object} [options]
* @param {AbortSignal} [options.signal]
* @return {Promise<bemap.GeocodingResponse>|bemap.Geocoder}
*/
bemap.Geocoder.prototype.geocode = function(request, options) {
if (!(request instanceof bemap.GeocodingRequest)) {
return legacyGeocode.call(this, request, options);
}
// Map GeocodingRequest → AutocompleteGeocodingRequest (forward geocoding
// is served by the autocomplete endpoint per the Flutter SDK contract).
var place = request.place;
if (!place && request.address) {
// Compose a one-line place string from the structured address.
var addr = (typeof request.address.toJson === 'function')
? request.address.toJson() : request.address;
var parts = [];
if (addr.streetNumber) parts.push(addr.streetNumber);
if (addr.street) parts.push(addr.street);
if (addr.postalCode) parts.push(addr.postalCode);
if (addr.city) parts.push(addr.city);
if (addr.country) parts.push(addr.country);
place = parts.join(' ');
}
var ac = new bemap.AutocompleteGeocodingRequest({
place: place || '',
language: request.language || 'en',
coordinate: request.proximity,
boundingBox: request.boundingBox,
countryCode: (request.address && request.address.countryCode) || null,
addressDetails: (request.addressDetails === undefined) ? true : !!request.addressDetails
});
var body = ac.toJson();
if (!body.geoserver) body.geoserver = (options && options.geoserver) || this.ctx.getGeoserver();
return this._v2()._post('service/geocoding/autocomplete/1.0', body, options || {})
.then(function(json) {
// The autocomplete response uses `items[]` with per-item place /
// postalAddress / coordinate — exactly what parseGeocodingResponseV2
// already handles.
return bemap.parseGeocodingResponseV2(json);
});
};
/**
* Reverse-geocode through the same channel `bemap.ReverseGeocoder` uses
* (`POST service/geocoding/1.0/reverse`). Accepts either a
* `ReverseGeocodingRequest` (typed v1.5 path) or the legacy
* `{searchInfo: RevGeoSearchInfo, success, failed}` shape.
*
* @public
* @param {bemap.ReverseGeocodingRequest|Object} request
* @param {Object} [options]
* @return {Promise<bemap.GeocodingResponse>|bemap.Geocoder}
*/
bemap.Geocoder.prototype.revGeocode = function(request, options) {
if (!(request instanceof bemap.ReverseGeocodingRequest)) {
return legacyRevGeocode.call(this, request, options);
}
var body = request.toJson();
if (!body.geoserver) body.geoserver = (options && options.geoserver) || this.ctx.getGeoserver();
return this._v2()._post('service/geocoding/1.0/reverse', body, options || {})
.then(function(json) { return bemap.parseGeocodingResponseV2(json); });
};
/**
* Convenience alias for the typed reverse-geocoding path.
*
* @public
* @param {bemap.Coordinate|bemap.CoordinateSat} coordinate
* @param {Number} [radius=50]
* @param {Object} [options] Extra fields forwarded to ReverseGeocodingRequest.
* @return {Promise<bemap.GeocodingResponse>}
*/
bemap.Geocoder.prototype.reverseGeocode = function(coordinate, radius, options) {
var opts = options || {};
var req = new bemap.ReverseGeocodingRequest({
coordinate: coordinate,
radius: (typeof radius === 'number') ? radius : 50,
transportMode: opts.transportMode,
language: opts.language || this.language,
maxResult: opts.maxResult || this.maxResult,
options: opts.options,
geoserver: opts.geoserver
});
return this.revGeocode(req, { signal: opts.signal });
};
})();