"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 _resource = _interopRequireDefault(require("./resource"));

var ResourceManager = function () {
  function ResourceManager(props) {
    var _props$device;

    (0, _classCallCheck2.default)(this, ResourceManager);
    this.protocol = void 0;
    this._context = void 0;
    this._resources = void 0;
    this._consumers = void 0;
    this._pruneRequest = void 0;
    this.protocol = props.protocol || 'resource://';
    this._context = {
      device: props.device,
      gl: (_props$device = props.device) === null || _props$device === void 0 ? void 0 : _props$device.gl,
      resourceManager: this
    };
    this._resources = {};
    this._consumers = {};
    this._pruneRequest = null;
  }

  var _proto = ResourceManager.prototype;

  _proto.contains = function contains(resourceId) {
    if (resourceId.startsWith(this.protocol)) {
      return true;
    }

    return resourceId in this._resources;
  };

  _proto.add = function add(_ref) {
    var resourceId = _ref.resourceId,
        data = _ref.data,
        _ref$forceUpdate = _ref.forceUpdate,
        forceUpdate = _ref$forceUpdate === void 0 ? false : _ref$forceUpdate,
        _ref$persistent = _ref.persistent,
        persistent = _ref$persistent === void 0 ? true : _ref$persistent;
    var res = this._resources[resourceId];

    if (res) {
      res.setData(data, forceUpdate);
    } else {
      res = new _resource.default(resourceId, data, this._context);
      this._resources[resourceId] = res;
    }

    res.persistent = persistent;
  };

  _proto.remove = function remove(resourceId) {
    var res = this._resources[resourceId];

    if (res) {
      res.delete();
      delete this._resources[resourceId];
    }
  };

  _proto.unsubscribe = function unsubscribe(_ref2) {
    var consumerId = _ref2.consumerId;
    var consumer = this._consumers[consumerId];

    if (consumer) {
      for (var requestId in consumer) {
        var request = consumer[requestId];
        var resource = this._resources[request.resourceId];

        if (resource) {
          resource.unsubscribe(request);
        }
      }

      delete this._consumers[consumerId];
      this.prune();
    }
  };

  _proto.subscribe = function subscribe(_ref3) {
    var resourceId = _ref3.resourceId,
        onChange = _ref3.onChange,
        consumerId = _ref3.consumerId,
        _ref3$requestId = _ref3.requestId,
        requestId = _ref3$requestId === void 0 ? 'default' : _ref3$requestId;
    var resources = this._resources,
        protocol = this.protocol;

    if (resourceId.startsWith(protocol)) {
      resourceId = resourceId.replace(protocol, '');

      if (!resources[resourceId]) {
        this.add({
          resourceId: resourceId,
          data: null,
          persistent: false
        });
      }
    }

    var res = resources[resourceId];

    this._track(consumerId, requestId, res, onChange);

    if (res) {
      return res.getData();
    }

    return undefined;
  };

  _proto.prune = function prune() {
    var _this = this;

    if (!this._pruneRequest) {
      this._pruneRequest = setTimeout(function () {
        return _this._prune();
      }, 0);
    }
  };

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

  _proto._track = function _track(consumerId, requestId, resource, onChange) {
    var consumers = this._consumers;
    var consumer = consumers[consumerId] = consumers[consumerId] || {};
    var request = consumer[requestId];
    var oldResource = request && request.resourceId && this._resources[request.resourceId];

    if (oldResource) {
      oldResource.unsubscribe(request);
      this.prune();
    }

    if (resource) {
      if (request) {
        request.onChange = onChange;
        request.resourceId = resource.id;
      } else {
        request = {
          onChange: onChange,
          resourceId: resource.id
        };
      }

      consumer[requestId] = request;
      resource.subscribe(request);
    }
  };

  _proto._prune = function _prune() {
    this._pruneRequest = null;

    for (var _i = 0, _Object$keys = Object.keys(this._resources); _i < _Object$keys.length; _i++) {
      var key = _Object$keys[_i];
      var res = this._resources[key];

      if (!res.persistent && !res.inUse()) {
        res.delete();
        delete this._resources[key];
      }
    }
  };

  return ResourceManager;
}();

exports.default = ResourceManager;
//# sourceMappingURL=resource-manager.js.map