/**
* BeNomad BeMap JavaScript API - TraceRouteRequest
*
* Typed request for `bemap.TraceRoute.compute(request)` and
* `bemap.TraceRoute.computeRnc(request)`. Map-matches a GPS trace onto the
* road network; the response is the same shape as `RoutingV2.calculate()`:
* a `bemap.RoutingResponse`.
*
* Wire shape mirrors the BeMap server contract (cross-checked against
* `bemap-flutter-api/lib/service/trace_route/model/request/trace_route_request.dart`).
* Endpoint: `POST service/routing/1.0/traceroute`.
*
* Required wire fields: `destinations` (min. 2 points), `routingVehicleProfile`.
*
* @since 1.5.0
* @public
* @constructor
* @param {Object} [options]
* @param {Array.<bemap.TraceRouteDestination|bemap.CoordinateSat|bemap.Coordinate|Object>} [options.destinations]
* Trace samples in chronological order. Mixed-input types are auto-promoted.
* @param {bemap.RoutingVehicleProfile} [options.routingVehicleProfile]
* Required by the server. Defaults to a generic CAR profile when omitted.
* @param {Array.<String>} [options.routingCriterias] Subset of `bemap.RoutingCriteria.*` (e.g. AVOID_TOLLS). Supported server-side for traceroute.
* @param {Array.<String>} [options.options] Subset of `bemap.TraceRouteOptions.*`.
* @param {Date|Number|String} [options.departureTime] Epoch ms / Date / ISO local datetime.
* @param {Boolean} [options.adjustEta] Adjust ETA from GPS timestamps.
* @param {Boolean} [options.allowOffRoad] Default true server-side.
* @param {Number} [options.corridorRadius]
* @param {Array.<Object>} [options.fenceShapes]
* @param {String} [options.language] ISO 639-1.
* @param {Array.<Object>} [options.customData]
* @param {Array.<Object>} [options.preferredRoads]
* @param {Array.<Object>} [options.routingRoadBlocks]
* @param {String} [options.geoserver]
* @param {Number} [options.switchIndex]
* @param {String} [options.requestId]
*/
bemap.TraceRouteRequest = function(options) {
var opts = options || {};
this.destinations = Array.isArray(opts.destinations) ? opts.destinations.slice() : [];
this.routingVehicleProfile = opts.routingVehicleProfile || null;
this.routingCriterias = Array.isArray(opts.routingCriterias) ? opts.routingCriterias.slice() : null;
this.options = Array.isArray(opts.options) ? opts.options.slice() : null;
this.departureTime = opts.departureTime || null;
this.adjustEta = (typeof opts.adjustEta === 'boolean') ? opts.adjustEta : null;
this.allowOffRoad = (typeof opts.allowOffRoad === 'boolean') ? opts.allowOffRoad : null;
this.corridorRadius = (typeof opts.corridorRadius === 'number') ? opts.corridorRadius : null;
this.fenceShapes = Array.isArray(opts.fenceShapes) ? opts.fenceShapes.slice() : null;
this.language = opts.language || null;
this.customData = Array.isArray(opts.customData) ? opts.customData.slice() : null;
this.preferredRoads = Array.isArray(opts.preferredRoads) ? opts.preferredRoads.slice() : null;
this.routingRoadBlocks = Array.isArray(opts.routingRoadBlocks) ? opts.routingRoadBlocks.slice() : null;
this.geoserver = opts.geoserver || null;
this.switchIndex = (typeof opts.switchIndex === 'number') ? opts.switchIndex : null;
this.requestId = opts.requestId || null;
};
/* Fluent setters */
bemap.TraceRouteRequest.prototype.addDestination = function(d) { this.destinations.push(d); return this; };
bemap.TraceRouteRequest.prototype.setDestinations = function(arr) {
this.destinations = Array.isArray(arr) ? arr.slice() : [];
return this;
};
bemap.TraceRouteRequest.prototype.setRoutingVehicleProfile = function(v) { this.routingVehicleProfile = v; return this; };
bemap.TraceRouteRequest.prototype.setOptions = function(o) {
this.options = Array.isArray(o) ? o.slice() : null;
return this;
};
bemap.TraceRouteRequest.prototype.setLanguage = function(l) { this.language = l; return this; };
bemap.TraceRouteRequest.prototype.setDepartureTime = function(d) { this.departureTime = d; return this; };
bemap.TraceRouteRequest.prototype.setAdjustEta = function(b) { this.adjustEta = !!b; return this; };
bemap.TraceRouteRequest.prototype.setAllowOffRoad = function(b) { this.allowOffRoad = !!b; return this; };
bemap.TraceRouteRequest.prototype.setRequestId = function(id) { this.requestId = id; return this; };
bemap.TraceRouteRequest.prototype.setRoutingCriterias = function(c) { this.routingCriterias = Array.isArray(c) ? c.slice() : null; return this; };
bemap.TraceRouteRequest.prototype.setCorridorRadius = function(n) { this.corridorRadius = (typeof n === 'number') ? n : null; return this; };
bemap.TraceRouteRequest.prototype.setFenceShapes = function(a) { this.fenceShapes = Array.isArray(a) ? a.slice() : null; return this; };
bemap.TraceRouteRequest.prototype.setCustomData = function(a) { this.customData = Array.isArray(a) ? a.slice() : null; return this; };
bemap.TraceRouteRequest.prototype.setPreferredRoads = function(a) { this.preferredRoads = Array.isArray(a) ? a.slice() : null; return this; };
bemap.TraceRouteRequest.prototype.setRoutingRoadBlocks = function(a) { this.routingRoadBlocks = Array.isArray(a) ? a.slice() : null; return this; };
bemap.TraceRouteRequest.prototype.setGeoserver = function(g) { this.geoserver = g || null; return this; };
bemap.TraceRouteRequest.prototype.setSwitchIndex = function(n) { this.switchIndex = (typeof n === 'number') ? n : null; return this; };
/** @private */
bemap.TraceRouteRequest._serialisePoint = function(p) {
if (!p) return null;
if (p instanceof bemap.TraceRouteDestination) return p.toJson();
return new bemap.TraceRouteDestination({ coordinateSat: p }).toJson();
};
/** @private */
bemap.TraceRouteRequest._asEpochOrIso = function(v) {
if (v === null || v === undefined) return null;
if (v instanceof Date) return v.getTime();
if (typeof v === 'number') return v;
return String(v);
};
bemap.TraceRouteRequest.prototype.toJson = function() {
var body = {};
// Required wire fields
var pts = [];
for (var i = 0; i < this.destinations.length; i++) {
var s = bemap.TraceRouteRequest._serialisePoint(this.destinations[i]);
if (s) pts.push(s);
}
body.destinations = pts;
// routingVehicleProfile is required server-side — default to a generic CAR
// profile when the caller did not supply one. Spec'd in the Flutter SDK doc:
// "Default transport mode for TraceRoute is EMERGENCY". The JS API defaults
// to CAR for parity with how most demos run the service.
var vp = this.routingVehicleProfile;
if (vp) {
body.routingVehicleProfile = (typeof vp.toJson === 'function') ? vp.toJson() : vp;
} else {
body.routingVehicleProfile = { transportMode: bemap.TransportMode.CAR };
}
// Optional
if (this.options && this.options.length) body.options = this.options.slice();
if (this.routingCriterias && this.routingCriterias.length) body.routingCriterias = this.routingCriterias.slice();
var dep = bemap.TraceRouteRequest._asEpochOrIso(this.departureTime);
if (dep !== null) body.departureTime = dep;
if (this.adjustEta !== null) body.adjustEta = this.adjustEta;
if (this.allowOffRoad !== null) body.allowOffRoad = this.allowOffRoad;
if (this.corridorRadius !== null) body.corridorRadius = this.corridorRadius;
if (this.fenceShapes && this.fenceShapes.length) body.fenceShapes = this.fenceShapes.slice();
if (this.language) body.language = this.language;
if (this.customData && this.customData.length) body.customData = this.customData.slice();
if (this.preferredRoads && this.preferredRoads.length) body.preferredRoads = this.preferredRoads.slice();
if (this.routingRoadBlocks && this.routingRoadBlocks.length) body.routingRoadBlocks = this.routingRoadBlocks.slice();
if (this.geoserver) body.geoserver = this.geoserver;
if (this.switchIndex !== null) body.switchIndex = this.switchIndex;
return body;
};