"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = exports.RasterElevationTile = exports.RasterColorTile = exports.EMPTY_TEXTURE_ZOOM = void 0;
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
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 THREE = _interopRequireWildcard(require("three"));
var _LayeredMaterial = require("./LayeredMaterial");
var _XbilParser = require("../Parser/XbilParser");
var _Crs = _interopRequireDefault(require("../Core/Geographic/Crs"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
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; } }
var EMPTY_TEXTURE_ZOOM = -1;
exports.EMPTY_TEXTURE_ZOOM = EMPTY_TEXTURE_ZOOM;
var pitch = new THREE.Vector4();
function getIndiceWithPitch(i, pitch, w) {
  // Return corresponding indice in parent tile using pitch
  // normalized
  var currentY = Math.floor(i / w) / w; // normalized
  var newX = pitch.x + i % w / w * pitch.z;
  var newY = pitch.y + currentY * pitch.w;
  var newIndice = Math.floor(newY * w) * w + Math.floor(newX * w);
  return newIndice;
}

/**
 * A `RasterTile` is part of raster [`Layer`]{@link Layer} data.
 * This part is a spatial subdivision of the extent of a layer.
 * In the `RasterTile`, The data are converted on three.js textures.
 * This `RasterTile` textures are assigned to a `LayeredMaterial`.
 * This material is applied on terrain (TileMesh).
 * The color textures are mapped to color the terrain.
 * The elevation textures are used to displace vertex terrain.
 *
 * @class RasterTile
 */
var RasterTile = /*#__PURE__*/function (_THREE$EventDispatche) {
  (0, _inherits2["default"])(RasterTile, _THREE$EventDispatche);
  var _super = _createSuper(RasterTile);
  function RasterTile(material, layer) {
    var _this;
    (0, _classCallCheck2["default"])(this, RasterTile);
    _this = _super.call(this);
    _this.layer = layer;
    _this.crs = layer.parent.tileMatrixSets.indexOf(_Crs["default"].formatToTms(layer.crs));
    if (_this.crs == -1) {
      console.error('Unknown crs:', layer.crs);
    }
    _this.textures = [];
    _this.offsetScales = [];
    _this.level = EMPTY_TEXTURE_ZOOM;
    _this.material = material;
    _this._handlerCBEvent = function () {
      _this.material.layersNeedUpdate = true;
    };
    layer.addEventListener('visible-property-changed', _this._handlerCBEvent);
    layer.addEventListener('opacity-property-changed', _this._handlerCBEvent);
    return _this;
  }
  (0, _createClass2["default"])(RasterTile, [{
    key: "id",
    get: function get() {
      return this.layer.id;
    }
  }, {
    key: "opacity",
    get: function get() {
      return this.layer.opacity;
    }
  }, {
    key: "visible",
    get: function get() {
      return this.layer.visible;
    }
  }, {
    key: "initFromParent",
    value: function initFromParent(parent, extents) {
      if (parent && parent.level > this.level) {
        var index = 0;
        var _iterator = _createForOfIteratorHelper(extents),
          _step;
        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var c = _step.value;
            var _iterator2 = _createForOfIteratorHelper(parent.textures),
              _step2;
            try {
              for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
                var texture = _step2.value;
                if (c.isInside(texture.extent)) {
                  this.setTexture(index++, texture, c.offsetToParent(texture.extent));
                  break;
                }
              }
            } catch (err) {
              _iterator2.e(err);
            } finally {
              _iterator2.f();
            }
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }
      }
    }
  }, {
    key: "dispose",
    value: function dispose(removeEvent) {
      if (removeEvent) {
        this.layer.removeEventListener('visible-property-changed', this._handlerCBEvent);
        this.layer.removeEventListener('opacity-property-changed', this._handlerCBEvent);
        // dispose all events
        this._listeners = {};
      }
      // TODO: WARNING  verify if textures to dispose aren't attached with ancestor
      var _iterator3 = _createForOfIteratorHelper(this.textures),
        _step3;
      try {
        for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
          var texture = _step3.value;
          if (texture.isTexture) {
            texture.dispose();
          }
        }
      } catch (err) {
        _iterator3.e(err);
      } finally {
        _iterator3.f();
      }
      this.level = EMPTY_TEXTURE_ZOOM;
      this.textures = [];
      this.offsetScales = [];
      this.material.layersNeedUpdate = true;
    }
  }, {
    key: "setTexture",
    value: function setTexture(index, texture, offsetScale) {
      this.level = texture && index == 0 ? texture.extent.zoom : this.level;
      this.textures[index] = texture || null;
      this.offsetScales[index] = offsetScale;
      this.material.layersNeedUpdate = true;
    }
  }, {
    key: "setTextures",
    value: function setTextures(textures, pitchs) {
      this.dispose(false);
      for (var i = 0, il = textures.length; i < il; ++i) {
        this.setTexture(i, textures[i], pitchs[i]);
      }
    }
  }]);
  return RasterTile;
}(THREE.EventDispatcher);
var _default = RasterTile;
exports["default"] = _default;
var RasterColorTile = /*#__PURE__*/function (_RasterTile) {
  (0, _inherits2["default"])(RasterColorTile, _RasterTile);
  var _super2 = _createSuper(RasterColorTile);
  function RasterColorTile() {
    (0, _classCallCheck2["default"])(this, RasterColorTile);
    return _super2.apply(this, arguments);
  }
  (0, _createClass2["default"])(RasterColorTile, [{
    key: "effect_type",
    get: function get() {
      return this.layer.effect_type;
    }
  }, {
    key: "effect_parameter",
    get: function get() {
      return this.layer.effect_parameter;
    }
  }, {
    key: "transparent",
    get: function get() {
      return this.layer.transparent;
    }
  }]);
  return RasterColorTile;
}(RasterTile);
exports.RasterColorTile = RasterColorTile;
var RasterElevationTile = /*#__PURE__*/function (_RasterTile2) {
  (0, _inherits2["default"])(RasterElevationTile, _RasterTile2);
  var _super3 = _createSuper(RasterElevationTile);
  function RasterElevationTile(material, layer) {
    var _layer$bias, _layer$mode, _layer$zmin, _layer$zmax;
    var _this2;
    (0, _classCallCheck2["default"])(this, RasterElevationTile);
    _this2 = _super3.call(this, material, layer);
    var defaultEle = {
      bias: 0,
      mode: _LayeredMaterial.ELEVATION_MODES.DATA,
      zmin: -Infinity,
      zmax: Infinity
    };
    _this2.scaleFactor = 1.0;

    // Define elevation properties
    if (layer.useRgbaTextureElevation) {
      defaultEle.mode = _LayeredMaterial.ELEVATION_MODES.RGBA;
      defaultEle.zmax = 5000;
      throw new Error('Restore this feature');
    } else if (layer.useColorTextureElevation) {
      _this2.scaleFactor = layer.colorTextureElevationMaxZ - layer.colorTextureElevationMinZ;
      defaultEle.mode = _LayeredMaterial.ELEVATION_MODES.COLOR;
      defaultEle.bias = layer.colorTextureElevationMinZ;
      _this2.min = _this2.layer.colorTextureElevationMinZ;
      _this2.max = _this2.layer.colorTextureElevationMaxZ;
    } else {
      _this2.min = 0;
      _this2.max = 0;
    }
    _this2.bias = (_layer$bias = layer.bias) !== null && _layer$bias !== void 0 ? _layer$bias : defaultEle.bias;
    _this2.mode = (_layer$mode = layer.mode) !== null && _layer$mode !== void 0 ? _layer$mode : defaultEle.mode;
    _this2.zmin = (_layer$zmin = layer.zmin) !== null && _layer$zmin !== void 0 ? _layer$zmin : defaultEle.zmin;
    _this2.zmax = (_layer$zmax = layer.zmax) !== null && _layer$zmax !== void 0 ? _layer$zmax : defaultEle.zmax;
    layer.addEventListener('scale-property-changed', _this2._handlerCBEvent);
    return _this2;
  }
  (0, _createClass2["default"])(RasterElevationTile, [{
    key: "scale",
    get: function get() {
      return this.layer.scale * this.scaleFactor;
    }
  }, {
    key: "dispose",
    value: function dispose(removeEvent) {
      (0, _get2["default"])((0, _getPrototypeOf2["default"])(RasterElevationTile.prototype), "dispose", this).call(this, removeEvent);
      if (removeEvent) {
        this.layer.removeEventListener('scale-property-changed', this._handlerCBEvent);
      }
    }
  }, {
    key: "initFromParent",
    value: function initFromParent(parent, extents) {
      var currentLevel = this.level;
      (0, _get2["default"])((0, _getPrototypeOf2["default"])(RasterElevationTile.prototype), "initFromParent", this).call(this, parent, extents);
      this.updateMinMaxElevation();
      if (currentLevel !== this.level) {
        this.dispatchEvent({
          type: 'rasterElevationLevelChanged',
          node: this
        });
      }
    }
  }, {
    key: "setTextures",
    value: function setTextures(textures, offsetScales) {
      var currentLevel = this.level;
      this.replaceNoDataValueFromTexture(textures[0]);
      (0, _get2["default"])((0, _getPrototypeOf2["default"])(RasterElevationTile.prototype), "setTextures", this).call(this, textures, offsetScales);
      this.updateMinMaxElevation();
      if (currentLevel !== this.level) {
        this.dispatchEvent({
          type: 'rasterElevationLevelChanged',
          node: this
        });
      }
    }
  }, {
    key: "updateMinMaxElevation",
    value: function updateMinMaxElevation() {
      if (this.textures[0] && !this.layer.useColorTextureElevation) {
        var _computeMinMaxElevati = (0, _XbilParser.computeMinMaxElevation)(this.textures[0], this.offsetScales[0], {
            noDataValue: this.layer.noDataValue,
            zmin: this.layer.zmin,
            zmax: this.layer.zmax
          }),
          min = _computeMinMaxElevati.min,
          max = _computeMinMaxElevati.max;
        if (this.min != min || this.max != max) {
          this.min = min;
          this.max = max;
        }
      }
    }
  }, {
    key: "replaceNoDataValueFromTexture",
    value: function replaceNoDataValueFromTexture(texture) {
      var nodatavalue = this.layer.noDataValue;
      if (nodatavalue == undefined) {
        return;
      }
      // replace no data value with parent texture value or 0 (if no significant value found).
      var parentTexture = this.textures[0];
      var parentDataElevation = parentTexture && parentTexture.image && parentTexture.image.data;
      var dataElevation = texture.image && texture.image.data;
      if (dataElevation && !(0, _XbilParser.checkNodeElevationTextureValidity)(dataElevation, nodatavalue)) {
        (0, _XbilParser.insertSignificantValuesFromParent)(dataElevation, parentDataElevation && dataParent(texture, parentTexture, parentDataElevation, pitch), nodatavalue);
      }
    }
  }]);
  return RasterElevationTile;
}(RasterTile);
exports.RasterElevationTile = RasterElevationTile;
function dataParent(texture, parentTexture, parentDataElevation, pitch) {
  texture.extent.offsetToParent(parentTexture.extent, pitch);
  return function (i) {
    return parentDataElevation[getIndiceWithPitch(i, pitch, 256)];
  };
}