"use strict";
/*global require*/
var defined = require("terriajs-cesium/Source/Core/defined").default;
var knockout = require("terriajs-cesium/Source/ThirdParty/knockout").default;
var overrideProperty = require("../Core/overrideProperty");
var FunctionParameter = require("./FunctionParameter");
var inherit = require("../Core/inherit");
var RegionProvider = require("../Map/RegionProvider");
var RegionProviderList = require("../Map/RegionProviderList");
/**
* A parameter that specifies a type of region.
*
* @alias RegionTypeParameter
* @constructor
* @extends FunctionParameter
*
* @param {Object} [options] Object with the following properties:
* @param {Terria} options.terria The Terria instance.
* @param {String} options.id The unique ID of this parameter.
* @param {String} [options.name] The name of this parameter. If not specified, the ID is used as the name.
* @param {String} [options.description] The description of the parameter.
* @param {String[]} [options.validRegionTypes] The region types from which this RegionTypeParameter selects. If this parameter is not specified, all region types
* known to {@link Terria} may be selected.
*/
var RegionTypeParameter = function(options) {
FunctionParameter.call(this, options);
this._regionProviderPromise = undefined;
this._regionProviderList = undefined;
this.validRegionTypes = options.validRegionTypes;
// Track this so that defaultValue can update once regionProviderList is known.
knockout.track(this, ["_regionProviderList"]);
/**
* Gets the default region provider if the user has not specified one. If region-mapped data
* is loaded on the map, this property returns the {@link RegionProvider} of the topmost
* region-mapped catalog item. Otherwise, it returns the first region provider. If the
* parameter has not yet been loaded, this property returns undefined.
* @memberof RegionTypeParameter.prototype
* @type {RegionProvider}
*/
overrideProperty(this, "defaultValue", {
get: function() {
if (defined(this._defaultValue)) {
return this._defaultValue;
}
const nowViewingItems = this.terria.nowViewing.items;
if (nowViewingItems.length > 0) {
for (let i = 0; i < nowViewingItems.length; ++i) {
const item = nowViewingItems[i];
if (
defined(item.regionMapping) &&
defined(item.regionMapping.regionDetails) &&
item.regionMapping.regionDetails.length > 0
) {
return item.regionMapping.regionDetails[0].regionProvider;
}
}
}
if (
defined(this._regionProviderList) &&
this._regionProviderList.length > 0
) {
return this._regionProviderList[0];
}
// No defaults available; have we requested the region providers yet?
this.load();
return undefined;
}
});
};
/**
* Resolves value that may be either a {@link RegionProvider} or a {@link RegionTypeParameter}
* to a {@link RegionProvider}.
* @param {RegionProvider|RegionTypeParameter} regionProviderOrParameter The region provider or parameter.
* @return {RegionProvider} If `regionProviderOrParameter` is a {@link RegionProvider}, that value is returned. If it is a
* {@link RegionTypeParameter}, the value of the parameter is returned.
* The return value may be undefined if `regionProviderOrParameter` is undefined, or if the value of the
* region type parameter is undefined.
*/
RegionTypeParameter.resolveRegionProvider = function(
regionProviderOrParameter
) {
if (regionProviderOrParameter instanceof RegionProvider) {
return regionProviderOrParameter;
} else if (regionProviderOrParameter instanceof RegionTypeParameter) {
return regionProviderOrParameter.value;
} else {
return undefined;
}
};
inherit(FunctionParameter, RegionTypeParameter);
Object.defineProperties(RegionTypeParameter.prototype, {
/**
* Gets the type of this parameter.
* @memberof RegionTypeParameter.prototype
* @type {String}
*/
type: {
get: function() {
return "regionType";
}
}
/**
* Gets or sets the value of this parameter.
* @memberof RegionTypeParameter.prototype
* @member {RegionProvider} value
*/
});
RegionTypeParameter.prototype._load = function() {
return this.getAllRegionTypes();
};
/**
* Gets all list of region types that may be selected for this parameter.
* Also caches the promise in this._regionProviderPromise, and the promise result in
* this._regionProviderList.
* @return {Promise.<RegionProvider[]>} [description]
*/
RegionTypeParameter.prototype.getAllRegionTypes = function() {
var that = this;
if (defined(this._regionProviderPromise)) {
return this._regionProviderPromise;
}
this._regionProviderPromise = RegionProviderList.fromUrl(
this.terria.configParameters.regionMappingDefinitionsUrl,
this.terria.corsProxy
).then(function(regionProviderList) {
var result;
if (!defined(that.validRegionTypes)) {
result = regionProviderList.regionProviders;
} else {
result = regionProviderList.regionProviders.filter(function(
regionProvider
) {
return that.validRegionTypes.indexOf(regionProvider.regionType) >= 0;
});
}
// Filter out region types that don't have a WMS server associated (e.g. those that are purely vector tile)
result = result.filter(function(regionProvider) {
return defined(regionProvider.analyticsWmsServer);
});
that._regionProviderList = result;
return result;
});
return this._regionProviderPromise;
};
module.exports = RegionTypeParameter;