import { Utils } from '../common/Utils';
const __ = {
private: Symbol('private'),
}
// #region Private Functions
// #endregion
/**
* @class ActionManager
* The action manager.
* @memberof THING
* @public
*/
class ActionManager {
constructor() {
this[__.private] = {};
let _private = this[__.private];
_private.objects = [];
_private.actions = new Map();
_private.app = Utils.getCurrentApp();
}
processAction(action, candidateMode, target, options, delay) {
let _private = this[__.private];
delay = Utils.parseValue(delay, 0);
return new Promise((resolve, reject) => {
if (delay) {
Utils.setTimeout(_doAction, delay);
}
else {
_doAction();
}
function _doAction() {
let promises = [];
// Use target to filter objects
if (target) {
let objects = candidateMode ? _private.objects : _private.app.objectManager.objects;
for (let i = 0, l = objects.length; i < l; i++) {
let object = objects[i];
if (object.test(target)) {
let promise = action.onRun({
object,
options
});
promises.push(promise);
}
}
}
// Use app root without any target
else {
let promise = action.onRun({
// object: _private.app.root,
options
});
promises.push(promise);
}
Promise.all(promises).then(resolve, reject);
}
});
}
dispose() {
let _private = this[__.private];
_private.app = null;
_private.objects.length = 0;
_private.actions.clear();
}
async _execute(messages) {
let _private = this[__.private];
for (let msg of messages) {
let { type, candidateMode, target, params, delay, waitForComplete } = msg;
let action = _private.actions.get(type);
if (!action) {
continue;
}
// process action
if (waitForComplete) {
await this.processAction(action, candidateMode, target, params, delay);
}
else {
this.processAction(action, candidateMode, target, params, delay);
}
}
}
/**
* Register action.
* @param {String} name The action unique name.
* @param {THING.BaseAction} action The action.
* @public
*/
register(name, action) {
let _private = this[__.private];
_private.actions.set(name, action);
}
/**
* Register action.
* @param {String} name The action unique name.
* @param {THING.BaseAction} action The action.
* @deprecated 2.7
* @private
*/
registerAction(name, action) {
this.register(name, action);
}
/**
* Unregister action.
* @param {String} name The action unique name.
* @public
*/
unregister(name) {
let _private = this[__.private];
_private.actions.delete(name);
}
/**
* Unregister action.
* @param {String} name The action unique name.
* @deprecated 2.7
* @private
*/
unregisterAction(name) {
this.unregister(name);
}
addListener(object) {
if (!object) {
return;
}
let _private = this[__.private];
if (object.isSelector) {
object.forEach(obj => {
_private.objects.push(obj);
});
}
else {
_private.objects.push(object);
}
}
removeListener(object) {
if (!object) {
return;
}
let _private = this[__.private];
if (object.isSelector) {
object.forEach(obj => {
let index = _private.objects.indexOf(obj);
if (index !== -1) {
_private.objects.splice(index, 1);
}
});
}
else {
let index = _private.objects.indexOf(object);
if (index !== -1) {
_private.objects.splice(index, 1);
}
}
}
/**
* The action message data.
* @typedef {Object} ActionMessageData
* @property {String} type The action type.
* @property {String} target The target to filer object what to process this action, if not provide then indicates use app's root as target object.
* @property {Object} params The parameters what pass to action.
* @property {Number} delay The delay to start performing the current action.
* @property {Boolean} waitForComplete Wait for the current action to complete before executing the next action, The default is false.
*/
/**
* Run actions.
* @param {Array<ActionMessageData>} messages The messages data.
* @example
* app.actionManager.run([
* {
* type: 'CameraFlyTo',
* params: {
* position: [10, 10, 5],
* target: [0, 0, 0],
* time: 1000
* },
* delay: 1000,
* waitForComplete: true
* },
* {
* type: 'CreateObject',
* params: {
* type: 'Box',
* name: 'box01'
* },
* delay: 1000,
* waitForComplete: true
* },
* {
* type: 'ObjectSetColor',
* target: 'box01',
* params: {
* color: 'red'
* },
* delay: 1000,
* waitForComplete: true
* }
* ]);
* @public
*/
run(messages) {
if (!messages) {
return;
}
if (Utils.isArray(messages)) {
this._execute(messages.slice(0));
}
else {
this._execute([messages]);
}
}
/**
* Run actions.
* @param {Array<ActionMessageData>} messages The messages data.
* @deprecated 2.7
* @private
*/
push(messages) {
this.run(messages);
}
getActionByName(name) {
let _private = this[__.private];
return _private.actions.get(name);
}
}
export { ActionManager }