text: /**
   * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
   *
   * @author David Sehnal <david.sehnal@gmail.com>
   * @author Alexander Rose <alexander.rose@weirdbyte.de>
   */
  import { __assign, __awaiter, __generator } from "tslib";
  import { UUID } from './uuid';
  import { iterableToArray } from '../mol-data/util';
  import { ajaxGet, readFromFile } from './data-source';
  import { Task } from '../mol-task';
  export { AssetManager, Asset };
  var Asset;
  (function (Asset) {
      function Url(url, options) {
          return __assign({ kind: 'url', id: UUID.create22(), url: url }, options);
      }
      Asset.Url = Url;
      function File(file) {
          return { kind: 'file', id: UUID.create22(), name: file.name, file: file };
      }
      Asset.File = File;
      function isUrl(x) {
          return (x === null || x === void 0 ? void 0 : x.kind) === 'url';
      }
      Asset.isUrl = isUrl;
      function isFile(x) {
          return (x === null || x === void 0 ? void 0 : x.kind) === 'file';
      }
      Asset.isFile = isFile;
      function Wrapper(data, asset, manager) {
          return {
              data: data,
              dispose: function () {
                  manager.release(asset);
              }
          };
      }
      Asset.Wrapper = Wrapper;
      function getUrl(url) {
          return typeof url === 'string' ? url : url.url;
      }
      Asset.getUrl = getUrl;
      function getUrlAsset(manager, url, body) {
          if (typeof url === 'string') {
              var asset = manager.tryFindUrl(url, body);
              return asset || Url(url, { body: body });
          }
          return url;
      }
      Asset.getUrlAsset = getUrlAsset;
  })(Asset || (Asset = {}));
  var AssetManager = /** @class */ (function () {
      function AssetManager() {
          // TODO: add URL based ref-counted cache?
          // TODO: when serializing, check for duplicates?
          this._assets = new Map();
      }
      Object.defineProperty(AssetManager.prototype, "assets", {
          get: function () {
              return iterableToArray(this._assets.values());
          },
          enumerable: false,
          configurable: true
      });
      AssetManager.prototype.tryFindUrl = function (url, body) {
          var assets = this.assets.values();
          while (true) {
              var v = assets.next();
              if (v.done)
                  return;
              var asset = v.value.asset;
              if (Asset.isUrl(asset) && asset.url === url && (asset.body || '') === (body || ''))
                  return asset;
          }
      };
      AssetManager.prototype.set = function (asset, file) {
          this._assets.set(asset.id, { asset: asset, file: file, refCount: 0 });
      };
      AssetManager.prototype.resolve = function (asset, type, store) {
          var _this = this;
          if (store === void 0) { store = true; }
          if (Asset.isUrl(asset)) {
              return Task.create("Download ".concat(asset.title || asset.url), function (ctx) { return __awaiter(_this, void 0, void 0, function () {
                  var entry, _a, _b, _c, _d, data, file, _e, _f;
                  return __generator(this, function (_g) {
                      switch (_g.label) {
                          case 0:
                              if (!this._assets.has(asset.id)) return [3 /*break*/, 2];
                              entry = this._assets.get(asset.id);
                              entry.refCount++;
                              _b = (_a = Asset).Wrapper;
                              return [4 /*yield*/, readFromFile(entry.file, type).runInContext(ctx)];
                          case 1: return [2 /*return*/, _b.apply(_a, [_g.sent(), asset, this])];
                          case 2:
                              if (!!store) return [3 /*break*/, 4];
                              _d = (_c = Asset).Wrapper;
                              return [4 /*yield*/, ajaxGet(__assign(__assign({}, asset), { type: type })).runInContext(ctx)];
                          case 3: return [2 /*return*/, _d.apply(_c, [_g.sent(), asset, this])];
                          case 4: return [4 /*yield*/, ajaxGet(__assign(__assign({}, asset), { type: 'binary' })).runInContext(ctx)];
                          case 5:
                              data = _g.sent();
                              file = new File([data], 'raw-data');
                              this._assets.set(asset.id, { asset: asset, file: file, refCount: 1 });
                              _f = (_e = Asset).Wrapper;
                              return [4 /*yield*/, readFromFile(file, type).runInContext(ctx)];
                          case 6: return [2 /*return*/, _f.apply(_e, [_g.sent(), asset, this])];
                      }
                  });
              }); });
          }
          else {
              return Task.create("Read ".concat(asset.name), function (ctx) { return __awaiter(_this, void 0, void 0, function () {
                  var entry, _a, _b, _c, _d;
                  return __generator(this, function (_e) {
                      switch (_e.label) {
                          case 0:
                              if (!this._assets.has(asset.id)) return [3 /*break*/, 2];
                              entry = this._assets.get(asset.id);
                              entry.refCount++;
                              _b = (_a = Asset).Wrapper;
                              return [4 /*yield*/, readFromFile(entry.file, type).runInContext(ctx)];
                          case 1: return [2 /*return*/, _b.apply(_a, [_e.sent(), asset, this])];
                          case 2:
                              if (!(asset.file instanceof File)) {
                                  throw new Error("Cannot resolve file asset '".concat(asset.name, "' (").concat(asset.id, ")"));
                              }
                              if (store) {
                                  this._assets.set(asset.id, { asset: asset, file: asset.file, refCount: 1 });
                              }
                              _d = (_c = Asset).Wrapper;
                              return [4 /*yield*/, readFromFile(asset.file, type).runInContext(ctx)];
                          case 3: return [2 /*return*/, _d.apply(_c, [_e.sent(), asset, this])];
                      }
                  });
              }); });
          }
      };
      AssetManager.prototype.release = function (asset) {
          var entry = this._assets.get(asset.id);
          if (!entry)
              return;
          entry.refCount--;
          if (entry.refCount <= 0)
              this._assets.delete(asset.id);
      };
      return AssetManager;
  }());
  //# sourceMappingURL=assets.js.map