"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 _engine = require("@luma.gl/engine");

var _shaderlib = require("../shaderlib");

var _constants = require("../lifecycle/constants");

var _log = _interopRequireDefault(require("../utils/log"));

var _debug = _interopRequireDefault(require("../debug"));

var _flatten = require("../utils/flatten");

var _stats = require("@probe.gl/stats");

var _resourceManager = _interopRequireDefault(require("./resource/resource-manager"));

var _viewport2 = _interopRequireDefault(require("../viewports/viewport"));

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; }

var TRACE_SET_LAYERS = 'layerManager.setLayers';
var TRACE_ACTIVATE_VIEWPORT = 'layerManager.activateViewport';

var LayerManager = function () {
  function LayerManager(device, props) {
    var _this = this;

    (0, _classCallCheck2.default)(this, LayerManager);
    this.layers = void 0;
    this.context = void 0;
    this.resourceManager = void 0;
    this._lastRenderedLayers = [];
    this._needsRedraw = false;
    this._needsUpdate = false;
    this._nextLayers = null;
    this._debug = false;

    this.activateViewport = function (viewport) {
      (0, _debug.default)(TRACE_ACTIVATE_VIEWPORT, _this, viewport);

      if (viewport) {
        _this.context.viewport = viewport;
      }
    };

    var _ref = props || {},
        deck = _ref.deck,
        stats = _ref.stats,
        _viewport = _ref.viewport,
        timeline = _ref.timeline;

    this.layers = [];
    this.resourceManager = new _resourceManager.default({
      device: device,
      protocol: 'deck://'
    });
    this.context = {
      mousePosition: null,
      userData: {},
      layerManager: this,
      device: device,
      gl: device === null || device === void 0 ? void 0 : device.gl,
      deck: deck,
      shaderAssembler: (0, _shaderlib.getShaderAssembler)(),
      pipelineFactory: device && (0, _shaderlib.getPipelineFactory)(device),
      renderPass: undefined,
      stats: stats || new _stats.Stats({
        id: 'deck.gl'
      }),
      viewport: _viewport || new _viewport2.default({
        id: 'DEFAULT-INITIAL-VIEWPORT'
      }),
      timeline: timeline || new _engine.Timeline(),
      resourceManager: this.resourceManager,
      onError: undefined
    };
    Object.seal(this);
  }

  var _proto = LayerManager.prototype;

  _proto.finalize = function finalize() {
    this.resourceManager.finalize();

    var _iterator = _createForOfIteratorHelper(this.layers),
        _step;

    try {
      for (_iterator.s(); !(_step = _iterator.n()).done;) {
        var layer = _step.value;

        this._finalizeLayer(layer);
      }
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }
  };

  _proto.needsRedraw = function needsRedraw() {
    var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
      clearRedrawFlags: false
    };
    var redraw = this._needsRedraw;

    if (opts.clearRedrawFlags) {
      this._needsRedraw = false;
    }

    var _iterator2 = _createForOfIteratorHelper(this.layers),
        _step2;

    try {
      for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
        var layer = _step2.value;
        var layerNeedsRedraw = layer.getNeedsRedraw(opts);
        redraw = redraw || layerNeedsRedraw;
      }
    } catch (err) {
      _iterator2.e(err);
    } finally {
      _iterator2.f();
    }

    return redraw;
  };

  _proto.needsUpdate = function needsUpdate() {
    if (this._nextLayers && this._nextLayers !== this._lastRenderedLayers) {
      return 'layers changed';
    }

    return this._needsUpdate;
  };

  _proto.setNeedsRedraw = function setNeedsRedraw(reason) {
    this._needsRedraw = this._needsRedraw || reason;
  };

  _proto.setNeedsUpdate = function setNeedsUpdate(reason) {
    this._needsUpdate = this._needsUpdate || reason;
  };

  _proto.getLayers = function getLayers() {
    var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
        layerIds = _ref2.layerIds;

    return layerIds ? this.layers.filter(function (layer) {
      return layerIds.find(function (layerId) {
        return layer.id.indexOf(layerId) === 0;
      });
    }) : this.layers;
  };

  _proto.setProps = function setProps(props) {
    if ('debug' in props) {
      this._debug = props.debug;
    }

    if ('userData' in props) {
      this.context.userData = props.userData;
    }

    if ('layers' in props) {
      this._nextLayers = props.layers;
    }

    if ('onError' in props) {
      this.context.onError = props.onError;
    }
  };

  _proto.setLayers = function setLayers(newLayers, reason) {
    (0, _debug.default)(TRACE_SET_LAYERS, this, reason, newLayers);
    this._lastRenderedLayers = newLayers;
    var flatLayers = (0, _flatten.flatten)(newLayers, Boolean);

    var _iterator3 = _createForOfIteratorHelper(flatLayers),
        _step3;

    try {
      for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
        var layer = _step3.value;
        layer.context = this.context;
      }
    } catch (err) {
      _iterator3.e(err);
    } finally {
      _iterator3.f();
    }

    this._updateLayers(this.layers, flatLayers);
  };

  _proto.updateLayers = function updateLayers() {
    var reason = this.needsUpdate();

    if (reason) {
      this.setNeedsRedraw("updating layers: ".concat(reason));
      this.setLayers(this._nextLayers || this._lastRenderedLayers, reason);
    }

    this._nextLayers = null;
  };

  _proto._handleError = function _handleError(stage, error, layer) {
    layer.raiseError(error, "".concat(stage, " of ").concat(layer));
  };

  _proto._updateLayers = function _updateLayers(oldLayers, newLayers) {
    var oldLayerMap = {};

    var _iterator4 = _createForOfIteratorHelper(oldLayers),
        _step4;

    try {
      for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
        var oldLayer = _step4.value;

        if (oldLayerMap[oldLayer.id]) {
          _log.default.warn("Multiple old layers with same id ".concat(oldLayer.id))();
        } else {
          oldLayerMap[oldLayer.id] = oldLayer;
        }
      }
    } catch (err) {
      _iterator4.e(err);
    } finally {
      _iterator4.f();
    }

    var generatedLayers = [];

    this._updateSublayersRecursively(newLayers, oldLayerMap, generatedLayers);

    this._finalizeOldLayers(oldLayerMap);

    var needsUpdate = false;

    for (var _i = 0, _generatedLayers = generatedLayers; _i < _generatedLayers.length; _i++) {
      var layer = _generatedLayers[_i];

      if (layer.hasUniformTransition()) {
        needsUpdate = "Uniform transition in ".concat(layer);
        break;
      }
    }

    this._needsUpdate = needsUpdate;
    this.layers = generatedLayers;
  };

  _proto._updateSublayersRecursively = function _updateSublayersRecursively(newLayers, oldLayerMap, generatedLayers) {
    var _iterator5 = _createForOfIteratorHelper(newLayers),
        _step5;

    try {
      for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
        var newLayer = _step5.value;
        newLayer.context = this.context;
        var oldLayer = oldLayerMap[newLayer.id];

        if (oldLayer === null) {
          _log.default.warn("Multiple new layers with same id ".concat(newLayer.id))();
        }

        oldLayerMap[newLayer.id] = null;
        var sublayers = null;

        try {
          if (this._debug && oldLayer !== newLayer) {
            newLayer.validateProps();
          }

          if (!oldLayer) {
            this._initializeLayer(newLayer);
          } else {
            this._transferLayerState(oldLayer, newLayer);

            this._updateLayer(newLayer);
          }

          generatedLayers.push(newLayer);
          sublayers = newLayer.isComposite ? newLayer.getSubLayers() : null;
        } catch (err) {
          this._handleError('matching', err, newLayer);
        }

        if (sublayers) {
          this._updateSublayersRecursively(sublayers, oldLayerMap, generatedLayers);
        }
      }
    } catch (err) {
      _iterator5.e(err);
    } finally {
      _iterator5.f();
    }
  };

  _proto._finalizeOldLayers = function _finalizeOldLayers(oldLayerMap) {
    for (var _layerId in oldLayerMap) {
      var layer = oldLayerMap[_layerId];

      if (layer) {
        this._finalizeLayer(layer);
      }
    }
  };

  _proto._initializeLayer = function _initializeLayer(layer) {
    try {
      layer._initialize();

      layer.lifecycle = _constants.LIFECYCLE.INITIALIZED;
    } catch (err) {
      this._handleError('initialization', err, layer);
    }
  };

  _proto._transferLayerState = function _transferLayerState(oldLayer, newLayer) {
    newLayer._transferState(oldLayer);

    newLayer.lifecycle = _constants.LIFECYCLE.MATCHED;

    if (newLayer !== oldLayer) {
      oldLayer.lifecycle = _constants.LIFECYCLE.AWAITING_GC;
    }
  };

  _proto._updateLayer = function _updateLayer(layer) {
    try {
      layer._update();
    } catch (err) {
      this._handleError('update', err, layer);
    }
  };

  _proto._finalizeLayer = function _finalizeLayer(layer) {
    this._needsRedraw = this._needsRedraw || "finalized ".concat(layer);
    layer.lifecycle = _constants.LIFECYCLE.AWAITING_FINALIZATION;

    try {
      layer._finalize();

      layer.lifecycle = _constants.LIFECYCLE.FINALIZED;
    } catch (err) {
      this._handleError('finalization', err, layer);
    }
  };

  return LayerManager;
}();

exports.default = LayerManager;
//# sourceMappingURL=layer-manager.js.map