"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.configureTile = configureTile;
exports.default = void 0;
var THREE = _interopRequireWildcard(require("three"));
var _B3dmParser = _interopRequireDefault(require("../Parser/B3dmParser"));
var _PntsParser = _interopRequireDefault(require("../Parser/PntsParser"));
var _Fetcher = _interopRequireDefault(require("./Fetcher"));
var _ReferencingLayerProperties = _interopRequireDefault(require("../Layer/ReferencingLayerProperties"));
var _PointsMaterial = _interopRequireDefault(require("../Renderer/PointsMaterial"));
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; }
const utf8Decoder = new TextDecoder();
function b3dmToMesh(data, layer, url) {
  const urlBase = THREE.LoaderUtils.extractUrlBase(url);
  const options = {
    gltfUpAxis: layer.tileset.asset.gltfUpAxis,
    urlBase,
    overrideMaterials: layer.overrideMaterials,
    doNotPatchMaterial: layer.doNotPatchMaterial,
    opacity: layer.opacity,
    registeredExtensions: layer.registeredExtensions,
    layer
  };
  return _B3dmParser.default.parse(data, options).then(result => {
    const batchTable = result.batchTable;
    // object3d is actually a THREE.Scene
    const object3d = result.gltf.scene;
    return {
      batchTable,
      object3d
    };
  });
}
function pntsParse(data, layer) {
  return _PntsParser.default.parse(data, layer.registeredExtensions).then(result => {
    const material = layer.material ? layer.material.clone() : new _PointsMaterial.default({
      size: 0.05,
      mode: layer.pntsMode,
      shape: layer.pntsShape,
      classification: layer.classification,
      sizeMode: layer.pntsSizeMode,
      minAttenuatedSize: layer.pntsMinAttenuatedSize,
      maxAttenuatedSize: layer.pntsMaxAttenuatedSize
    });

    // refer material properties in the layer so when layers opacity and visibility is updated, the material is
    // automatically updated
    (0, _ReferencingLayerProperties.default)(material, layer);

    // creation points with geometry and material
    const points = new THREE.Points(result.point.geometry, material);
    if (result.point.offset) {
      points.position.copy(result.point.offset);
    }
    return {
      object3d: points,
      batchTable: result.batchTable
    };
  });
}
function configureTile(tile, layer, metadata, parent) {
  tile.frustumCulled = false;
  tile.layer = layer;

  // parse metadata
  if (metadata.transform) {
    tile.applyMatrix4(metadata.transform);
  }
  tile.geometricError = metadata.geometricError;
  tile.tileId = metadata.tileId;
  if (metadata.refine) {
    tile.additiveRefinement = metadata.refine.toUpperCase() === 'ADD';
  } else {
    tile.additiveRefinement = parent ? parent.additiveRefinement : false;
  }
  tile.viewerRequestVolume = metadata.viewerRequestVolume;
  tile.boundingVolume = metadata.boundingVolume;
  tile.updateMatrixWorld();
}
function executeCommand(command) {
  const layer = command.layer;
  const metadata = command.metadata;
  const tile = new THREE.Object3D();
  configureTile(tile, layer, metadata, command.requester);
  // Patch for supporting 3D Tiles pre 1.0 (metadata.content.url) and 1.0
  // (metadata.content.uri)
  const path = metadata.content && (metadata.content.url || metadata.content.uri);
  const setLayer = obj => {
    obj.userData.metadata = metadata;
    obj.layer = layer;
  };
  if (path) {
    // Check if we have relative or absolute url (with tileset's lopocs for example)
    const url = path.startsWith('http') ? path : metadata.baseURL + path;
    const supportedFormats = {
      b3dm: b3dmToMesh,
      pnts: pntsParse
    };
    return _Fetcher.default.arrayBuffer(url, layer.source.networkOptions).then(result => {
      if (result !== undefined) {
        let func;
        const magic = utf8Decoder.decode(new Uint8Array(result, 0, 4));
        if (magic[0] === '{') {
          result = JSON.parse(utf8Decoder.decode(new Uint8Array(result)));
          const newPrefix = url.slice(0, url.lastIndexOf('/') + 1);
          layer.tileset.extendTileset(result, metadata.tileId, newPrefix, layer.registeredExtensions);
        } else if (magic == 'b3dm') {
          func = supportedFormats.b3dm;
        } else if (magic == 'pnts') {
          func = supportedFormats.pnts;
        } else {
          return Promise.reject(`Unsupported magic code ${magic}`);
        }
        if (func) {
          // TODO: request should be delayed if there is a viewerRequestVolume
          return func(result, layer, url).then(content => {
            tile.content = content.object3d;
            if (content.batchTable) {
              tile.batchTable = content.batchTable;
            }
            tile.add(content.object3d);
            tile.traverse(setLayer);
            return tile;
          });
        }
      }
      tile.traverse(setLayer);
      return tile;
    });
  } else {
    tile.traverse(setLayer);
    return Promise.resolve(tile);
  }
}
var _default = {
  executeCommand
};
exports.default = _default;