"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _attribute = _interopRequireDefault(require("./attribute"));

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

var _memoize = _interopRequireDefault(require("../../utils/memoize"));

var _mathUtils = require("../../utils/math-utils");

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

var _attributeTransitionManager = _interopRequireDefault(require("./attribute-transition-manager"));

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

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_INVALIDATE = 'attributeManager.invalidate';
var TRACE_UPDATE_START = 'attributeManager.updateStart';
var TRACE_UPDATE_END = 'attributeManager.updateEnd';
var TRACE_ATTRIBUTE_UPDATE_START = 'attribute.updateStart';
var TRACE_ATTRIBUTE_ALLOCATE = 'attribute.allocate';
var TRACE_ATTRIBUTE_UPDATE_END = 'attribute.updateEnd';

var AttributeManager = function () {
  function AttributeManager(device) {
    var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
        _ref$id = _ref.id,
        id = _ref$id === void 0 ? 'attribute-manager' : _ref$id,
        stats = _ref.stats,
        timeline = _ref.timeline;

    (0, _classCallCheck2.default)(this, AttributeManager);
    this.id = void 0;
    this.device = void 0;
    this.attributes = void 0;
    this.updateTriggers = void 0;
    this.needsRedraw = void 0;
    this.userData = void 0;
    this.stats = void 0;
    this.attributeTransitionManager = void 0;
    this.mergeBoundsMemoized = (0, _memoize.default)(_mathUtils.mergeBounds);
    this.id = id;
    this.device = device;
    this.attributes = {};
    this.updateTriggers = {};
    this.needsRedraw = true;
    this.userData = {};
    this.stats = stats;
    this.attributeTransitionManager = new _attributeTransitionManager.default(device, {
      id: "".concat(id, "-transitions"),
      timeline: timeline
    });
    Object.seal(this);
  }

  var _proto = AttributeManager.prototype;

  _proto.finalize = function finalize() {
    for (var attributeName in this.attributes) {
      this.attributes[attributeName].delete();
    }

    this.attributeTransitionManager.finalize();
  };

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

  _proto.setNeedsRedraw = function setNeedsRedraw() {
    this.needsRedraw = true;
  };

  _proto.add = function add(attributes) {
    this._add(attributes);
  };

  _proto.addInstanced = function addInstanced(attributes) {
    this._add(attributes, {
      instanced: 1
    });
  };

  _proto.remove = function remove(attributeNameArray) {
    var _iterator = _createForOfIteratorHelper(attributeNameArray),
        _step;

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

        if (this.attributes[_name] !== undefined) {
          this.attributes[_name].delete();

          delete this.attributes[_name];
        }
      }
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }
  };

  _proto.invalidate = function invalidate(triggerName, dataRange) {
    var invalidatedAttributes = this._invalidateTrigger(triggerName, dataRange);

    (0, _debug.default)(TRACE_INVALIDATE, this, triggerName, invalidatedAttributes);
  };

  _proto.invalidateAll = function invalidateAll(dataRange) {
    for (var attributeName in this.attributes) {
      this.attributes[attributeName].setNeedsUpdate(attributeName, dataRange);
    }

    (0, _debug.default)(TRACE_INVALIDATE, this, 'all');
  };

  _proto.update = function update(_ref2) {
    var data = _ref2.data,
        numInstances = _ref2.numInstances,
        _ref2$startIndices = _ref2.startIndices,
        startIndices = _ref2$startIndices === void 0 ? null : _ref2$startIndices,
        transitions = _ref2.transitions,
        _ref2$props = _ref2.props,
        props = _ref2$props === void 0 ? {} : _ref2$props,
        _ref2$buffers = _ref2.buffers,
        buffers = _ref2$buffers === void 0 ? {} : _ref2$buffers,
        _ref2$context = _ref2.context,
        context = _ref2$context === void 0 ? {} : _ref2$context;
    var updated = false;
    (0, _debug.default)(TRACE_UPDATE_START, this);

    if (this.stats) {
      this.stats.get('Update Attributes').timeStart();
    }

    for (var attributeName in this.attributes) {
      var attribute = this.attributes[attributeName];
      var accessorName = attribute.settings.accessor;
      attribute.startIndices = startIndices;
      attribute.numInstances = numInstances;

      if (props[attributeName]) {
        _log.default.removed("props.".concat(attributeName), "data.attributes.".concat(attributeName))();
      }

      if (attribute.setExternalBuffer(buffers[attributeName])) {} else if (attribute.setBinaryValue(typeof accessorName === 'string' ? buffers[accessorName] : undefined, data.startIndices)) {} else if (typeof accessorName === 'string' && !buffers[accessorName] && attribute.setConstantValue(props[accessorName])) {} else if (attribute.needsUpdate()) {
        updated = true;

        this._updateAttribute({
          attribute: attribute,
          numInstances: numInstances,
          data: data,
          props: props,
          context: context
        });
      }

      this.needsRedraw = this.needsRedraw || attribute.needsRedraw();
    }

    if (updated) {
      (0, _debug.default)(TRACE_UPDATE_END, this, numInstances);
    }

    if (this.stats) {
      this.stats.get('Update Attributes').timeEnd();
    }

    this.attributeTransitionManager.update({
      attributes: this.attributes,
      numInstances: numInstances,
      transitions: transitions
    });
  };

  _proto.updateTransition = function updateTransition() {
    var attributeTransitionManager = this.attributeTransitionManager;
    var transitionUpdated = attributeTransitionManager.run();
    this.needsRedraw = this.needsRedraw || transitionUpdated;
    return transitionUpdated;
  };

  _proto.getAttributes = function getAttributes() {
    return this.attributes;
  };

  _proto.getBounds = function getBounds(attributeNames) {
    var _this = this;

    var bounds = attributeNames.map(function (attributeName) {
      var _this$attributes$attr;

      return (_this$attributes$attr = _this.attributes[attributeName]) === null || _this$attributes$attr === void 0 ? void 0 : _this$attributes$attr.getBounds();
    });
    return this.mergeBoundsMemoized(bounds);
  };

  _proto.getChangedAttributes = function getChangedAttributes() {
    var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
      clearChangedFlags: false
    };
    var attributes = this.attributes,
        attributeTransitionManager = this.attributeTransitionManager;

    var changedAttributes = _objectSpread({}, attributeTransitionManager.getAttributes());

    for (var attributeName in attributes) {
      var attribute = attributes[attributeName];

      if (attribute.needsRedraw(opts) && !attributeTransitionManager.hasAttribute(attributeName)) {
        changedAttributes[attributeName] = attribute;
      }
    }

    return changedAttributes;
  };

  _proto.getBufferLayouts = function getBufferLayouts(attributes) {
    var excludeAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

    if (!attributes) {
      attributes = this.getAttributes();
    }

    var bufferMaps = [];

    for (var attributeName in attributes) {
      if (!excludeAttributes[attributeName]) {
        bufferMaps.push(attributes[attributeName].getBufferLayout());
      }
    }

    return bufferMaps;
  };

  _proto._add = function _add(attributes) {
    var extraProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

    for (var attributeName in attributes) {
      var attribute = attributes[attributeName];
      this.attributes[attributeName] = this._createAttribute(attributeName, attribute, extraProps);
    }

    this._mapUpdateTriggersToAttributes();
  };

  _proto._createAttribute = function _createAttribute(name, attribute, extraProps) {
    var props = _objectSpread(_objectSpread({}, attribute), {}, {
      id: name,
      size: attribute.isIndexed && 1 || attribute.size || 1,
      divisor: extraProps.instanced ? 1 : attribute.divisor || 0
    });

    return new _attribute.default(this.device, props);
  };

  _proto._mapUpdateTriggersToAttributes = function _mapUpdateTriggersToAttributes() {
    var _this2 = this;

    var triggers = {};

    var _loop = function _loop(attributeName) {
      var attribute = _this2.attributes[attributeName];
      attribute.getUpdateTriggers().forEach(function (triggerName) {
        if (!triggers[triggerName]) {
          triggers[triggerName] = [];
        }

        triggers[triggerName].push(attributeName);
      });
    };

    for (var attributeName in this.attributes) {
      _loop(attributeName);
    }

    this.updateTriggers = triggers;
  };

  _proto._invalidateTrigger = function _invalidateTrigger(triggerName, dataRange) {
    var attributes = this.attributes,
        updateTriggers = this.updateTriggers;
    var invalidatedAttributes = updateTriggers[triggerName];

    if (invalidatedAttributes) {
      invalidatedAttributes.forEach(function (name) {
        var attribute = attributes[name];

        if (attribute) {
          attribute.setNeedsUpdate(attribute.id, dataRange);
        }
      });
    }

    return invalidatedAttributes;
  };

  _proto._updateAttribute = function _updateAttribute(opts) {
    var attribute = opts.attribute,
        numInstances = opts.numInstances;
    (0, _debug.default)(TRACE_ATTRIBUTE_UPDATE_START, attribute);

    if (attribute.constant) {
      attribute.setConstantValue(attribute.value);
      return;
    }

    if (attribute.allocate(numInstances)) {
      (0, _debug.default)(TRACE_ATTRIBUTE_ALLOCATE, attribute, numInstances);
    }

    var updated = attribute.updateBuffer(opts);

    if (updated) {
      this.needsRedraw = true;
      (0, _debug.default)(TRACE_ATTRIBUTE_UPDATE_END, attribute, numInstances);
    }
  };

  return AttributeManager;
}();

exports.default = AttributeManager;
//# sourceMappingURL=attribute-manager.js.map