"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _RasterLayer2 = _interopRequireDefault(require("./RasterLayer"));
var _LayeredMaterialNodeProcessing = require("../Process/LayeredMaterialNodeProcessing");
var _RasterTile = require("../Renderer/RasterTile");
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function () { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
/**
 * @property {boolean} isElevationLayer - Used to checkout whether this layer is
 * an ElevationLayer. Default is true. You should not change this, as it is used
 * internally for optimisation.
 * @property {number} noDataValue - Used to specify a **null** or **no data value** in the elevation terrain.
 * @property {number} [zmin] - Used to specify a minimum value for the elevation terrain (if the data goes lower, it will be clamped).
 * @property {number} [zmax] - Used to specify a maximum value for the elevation terrain (if the data goes higher, it will be clamped)
 * @property {number} scale - Used to apply a scale on the elevation value. It
 * can be used for exageration of the elevation, like in [this
 * example](https://www.itowns-project.org/itowns/examples/#plugins_pyramidal_tiff).
 * @property {boolean} useColorTextureElevation - the elevation is computed with one color texture channel,
 * `this.colorTextureElevationMaxZ` and `this.colorTextureElevationMinZ`.
 *
 * The formula is:
 *
 * ```js
 * elevation = color.r * (this.colorTextureElevationMaxZ - this.colorTextureElevationMinZ) + this.colorTextureElevationMinZ
 * ```
 * @property {number} colorTextureElevationMinZ - elevation minimum in `useColorTextureElevation` mode.
 * @property {number} colorTextureElevationMaxZ - elevation maximum in `useColorTextureElevation` mode.
 */
var ElevationLayer = /*#__PURE__*/function (_RasterLayer) {
  (0, _inherits2["default"])(ElevationLayer, _RasterLayer);
  var _super = _createSuper(ElevationLayer);
  /**
   * A simple layer, managing an elevation texture to add some reliefs on the
   * plane or globe view for example.
   *
   * @constructor
   * @extends Layer
   *
   * @param {string} id - The id of the layer, that should be unique. It is
   * not mandatory, but an error will be emitted if this layer is added a
   * {@link View} that already has a layer going by that id.
   * @param {Object} [config] - Optional configuration, all elements in it
   * will be merged as is in the layer. For example, if the configuration
   * contains three elements `name, protocol, extent`, these elements will be
   * available using `layer.name` or something else depending on the property
   * name.
   * @param {number} [config.noDataValue]   The value coding the noData in the data set
   * @param {Object} [config.clampValues] - Optional information for clamping
   * the elevation between a minimum and a maximum value
   * @param {number} [config.clampValues.min]   The minimum value to clamp the elevation
   * @param {number} [config.clampValues.max]   The maximum value to clamp the elevation
   *
   * @example
   * // Create an ElevationLayer
   * const elevation = new ElevationLayer('IGN_MNT', {
   *      source: new WMTSSource({
   *          "url": "https://wxs.ign.fr/altimetrie/geoportail/wmts",
   *           "crs": "EPSG:4326",
   *           "format": "image/x-bil;bits=32",
   *           "name": "ELEVATION.ELEVATIONGRIDCOVERAGE",
   *      }),
   * });
   *
   * // Add the layer
   * view.addLayer(elevation);
   */
  function ElevationLayer(id) {
    var _config$clampValues$m, _config$clampValues, _config$clampValues$m2, _config$clampValues2;
    var _this;
    var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
    (0, _classCallCheck2["default"])(this, ElevationLayer);
    _this = _super.call(this, id, config);
    if (config.zmin || config.zmax) {
      console.warn('Config using zmin and zmax are deprecated, use {clampValues: {min, max}} structure.');
    }
    _this.zmin = (_config$clampValues$m = (_config$clampValues = config.clampValues) === null || _config$clampValues === void 0 ? void 0 : _config$clampValues.min) !== null && _config$clampValues$m !== void 0 ? _config$clampValues$m : config.zmin;
    _this.zmax = (_config$clampValues$m2 = (_config$clampValues2 = config.clampValues) === null || _config$clampValues2 === void 0 ? void 0 : _config$clampValues2.max) !== null && _config$clampValues$m2 !== void 0 ? _config$clampValues$m2 : config.zmax;
    _this.isElevationLayer = true;
    _this.defineLayerProperty('scale', _this.scale || 1.0);
    return _this;
  }

  /**
   * Setup RasterElevationTile added to TileMesh. This RasterElevationTile handles
   * the elevation texture to displace TileMesh vertices.
   *
   * @param      {TileMesh}  node    The node to apply new RasterElevationTile;
   * @return     {RasterElevationTile}  The raster elevation node added.
   */
  (0, _createClass2["default"])(ElevationLayer, [{
    key: "setupRasterNode",
    value: function setupRasterNode(node) {
      var _this2 = this;
      var rasterElevationNode = new _RasterTile.RasterElevationTile(node.material, this);
      node.material.addLayer(rasterElevationNode);
      node.material.setSequenceElevation(this.id);
      // bounding box initialisation
      var updateBBox = function () {
        return node.setBBoxZ({
          min: rasterElevationNode.min,
          max: rasterElevationNode.max,
          scale: _this2.scale
        });
      };
      updateBBox();

      // listen elevation updating
      rasterElevationNode.addEventListener('rasterElevationLevelChanged', updateBBox);

      // listen scaling elevation updating
      this.addEventListener('scale-property-changed', updateBBox);
      // remove scaling elevation updating if node is removed
      node.addEventListener('dispose', function () {
        _this2.removeEventListener('scale-property-changed', updateBBox);
      });
      return rasterElevationNode;
    }
  }, {
    key: "update",
    value: function update(context, layer, node, parent) {
      return (0, _LayeredMaterialNodeProcessing.updateLayeredMaterialNodeElevation)(context, this, node, parent);
    }
  }]);
  return ElevationLayer;
}(_RasterLayer2["default"]);
var _default = ElevationLayer;
exports["default"] = _default;