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
* The base resource.
* @memberof THING
*/
class BaseResource extends RefCountObject {
constructor(param = {}) {
super();
this[__.private] = {};
let _private = this[__.private];
_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;
}
/**
* Wait for object load completed.
* @returns {Promise<any>}
*/
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;
}
/**
* Get the unique ID.
* @type {String}
*/
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
/**
* Check class type.
* @type {Boolean}
* @private
*/
get isBaseResource() {
return true;
}
// #endregion
}
export { BaseResource }