import { Flags, MathUtils, RefCountObject, ResolvablePromise } from '@uino/base-thing';
import { Utils } from '../common/Utils'
const __ = {
private: Symbol('private'),
}
const Flag = {
Loaded: 1 << 0,
}
/**
* @class BaseResource
* 基础资源。
* @memberof THING
* @extends THING.RefCountObject
* @public
*/
class BaseResource extends RefCountObject {
/**
* 基础资源类构造函数,用于初始化资源对象。
* @param {object} param - 初始参数对象,包含资源的配置和回调。
* @param {string} param.extras - 额外的资源信息,通常用于存储附加数据。
* @param {string} param.external - 外部资源的引用,可能用于加载外部文件。
* @param {Function} param.onComplete - 资源加载完成后的回调函数。
*/
constructor(param = {}) {
super();
this[__.private] = {};
let _private = this[__.private];
_private.app = param['app'] || Utils.getCurrentApp();
_private.uuid = MathUtils.generateUUID();
_private.flags = new Flags();
_private.pendingPromise = null;
_private.external = Utils.parseValue(param['extras'] || param['external'], null);
_private.context = null;
_private.complete = Utils.parseFunc(param['onComplete'] || param['complete']);
}
// #region Private
// #endregion
// #region Overrides
onDispose() {
let _private = this[__.private];
if (_private.context) {
_private.context.dispose();
_private.context = null;
}
_private.pendingPromise = null;
}
/**
* Notify complete.
* @private
*/
onNotifyComplete() {
let _private = this[__.private];
let pendingPromise = _private.pendingPromise;
if (pendingPromise) {
if (this.refCount) {
pendingPromise.resolve(this);
}
// Prevent dispose image in loading state
else {
pendingPromise.reject();
}
}
_private.flags.set(Flag.Loaded, true);
// Notify outside
if (_private.complete) {
_private.complete({ image: this });
_private.complete = null;
}
}
onNotifyError(ev) {
let _private = this[__.private];
// Here we must create pending promise to prevent calling waitForComplete() to wait it finished
_private.pendingPromise = _private.pendingPromise || new ResolvablePromise();
_private.pendingPromise.reject(ev);
}
// #endregion
/**
* Dispose.
* @private
*/
dispose() {
this.release();
}
/**
* Unload resource.
* @private
*/
unloadResource() {
if (!this.loaded) {
return;
}
let _private = this[__.private];
_private.flags.enable(Flag.Loaded, false);
_private.pendingPromise = null;
}
/**
* 等待资源加载完成。
* @returns {Promise<any>} 返回一个 Promise 对象。
* @public
* @example
* let resource = new THING.BaseResource();
* resource.waitForComplete().then((resource) => {
* console.log('Resource loaded');
* });
*/
waitForComplete() {
if (this.loaded) {
return Promise.resolve(this);
}
let _private = this[__.private];
_private.pendingPromise = _private.pendingPromise || new ResolvablePromise();
return _private.pendingPromise;
}
setContext(value) {
let _private = this[__.private];
_private.context = value;
}
/**
* Convert to string(always use uuid to stringify).
* @returns {string} 返回唯一标识符。
* @private
*/
toString() {
let _private = this[__.private];
return _private.uuid;
}
// #region Accessors
/**
* Get/Set the pending promise.
* @type {Promise<any>}
* @private
*/
get pendingPromise() {
let _private = this[__.private];
return _private.pendingPromise;
}
set pendingPromise(value) {
let _private = this[__.private];
_private.pendingPromise = value;
}
/**
* Check whether it's already disposed.
* @type {boolean}
* @private
*/
get disposed() {
return this.refCount == 0;
}
/**
* Get the external info.
* @type {object}
* @private
*/
get external() {
let _private = this[__.private];
return _private.external;
}
/**
* 获取唯一标识符。
* @type {string}
* @public
*/
get uuid() {
let _private = this[__.private];
return _private.uuid;
}
/**
* Get the loaded flag.
* @type {boolean}
*/
get loaded() {
let _private = this[__.private];
return _private.flags.has(Flag.Loaded);
}
/**
* Get the resource context.
* @type {object}
* @private
*/
get context() {
let _private = this[__.private];
return _private.context;
}
// #endregion
get app() {
let _private = this[__.private];
return _private.app;
}
/**
* 检查类类型。
* @type {boolean}
* @public
*/
get isBaseResource() {
return true;
}
// #endregion
}
export { BaseResource }