"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var THREE = _interopRequireWildcard(require("three"));
var _Crs = _interopRequireDefault(require("./Geographic/Crs"));
var _GeoidLayer = require("../Layer/GeoidLayer");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (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; }
/**
 * A TileMesh is a THREE.Mesh with a geometricError and an OBB
 * The objectId property of the material is the with the id of the TileMesh
 * @constructor
 * @param {TileGeometry} geometry - the tile geometry
 * @param {THREE.Material} material - a THREE.Material compatible with THREE.Mesh
 * @param {Layer} layer - the layer the tile is added to
 * @param {Extent} extent - the tile extent
 * @param {?number} level - the tile level (default = 0)
 */
class TileMesh extends THREE.Mesh {
  #_tms = new Map();
  #visible = true;
  constructor(geometry, material, layer, extent) {
    let level = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
    super(geometry, material);
    if (!extent) {
      throw new Error('extent is mandatory to build a TileMesh');
    }
    this.layer = layer;
    this.extent = extent;
    this.extent.zoom = level;
    this.level = level;
    this.material.objectId = this.id;
    this.obb = this.geometry.OBB.clone();
    this.boundingSphere = new THREE.Sphere();
    this.obb.box3D.getBoundingSphere(this.boundingSphere);
    for (const tms of layer.tileMatrixSets) {
      this.#_tms.set(tms, this.extent.tiledCovering(tms));
    }
    this.frustumCulled = false;
    this.matrixAutoUpdate = false;
    this.rotationAutoUpdate = false;
    this.layerUpdateState = {};
    this.isTileMesh = true;
    this.geoidHeight = 0;
    this.link = {};
    Object.defineProperty(this, 'visible', {
      get() {
        return this.#visible;
      },
      set(v) {
        if (this.#visible != v) {
          this.#visible = v;
          this.dispatchEvent({
            type: v ? 'shown' : 'hidden'
          });
        }
      }
    });
  }
  /**
   * If specified, update the min and max elevation of the OBB
   * and updates accordingly the bounding sphere and the geometric error
   *
   * @param {Object}  elevation
   * @param {number}  [elevation.min]
   * @param {number}  [elevation.max]
   * @param {number}  [elevation.scale]
   */
  setBBoxZ(elevation) {
    elevation.geoidHeight = (0, _GeoidLayer.geoidLayerIsVisible)(this.layer) ? this.geoidHeight : 0;
    this.obb.updateZ(elevation);
    if (this.horizonCullingPointElevationScaled) {
      this.horizonCullingPointElevationScaled.setLength(this.obb.z.delta + this.horizonCullingPoint.length());
    }
    this.obb.box3D.getBoundingSphere(this.boundingSphere);
  }
  getExtentsByProjection(crs) {
    return this.#_tms.get(_Crs.default.formatToTms(crs));
  }

  /**
   * Search for a common ancestor between this tile and another one. It goes
   * through parents on each side until one is found.
   *
   * @param {TileMesh} tile
   *
   * @return {TileMesh} the resulting common ancestor
   */
  findCommonAncestor(tile) {
    if (!tile) {
      return undefined;
    }
    if (tile.level == this.level) {
      if (tile.id == this.id) {
        return tile;
      } else if (tile.level != 0) {
        return this.parent.findCommonAncestor(tile.parent);
      } else {
        return undefined;
      }
    } else if (tile.level < this.level) {
      return this.parent.findCommonAncestor(tile);
    } else {
      return this.findCommonAncestor(tile.parent);
    }
  }
  onBeforeRender() {
    if (this.material.layersNeedUpdate) {
      this.material.updateLayersUniforms();
    }
  }
}
var _default = TileMesh;
exports.default = _default;