'use strict';
/**
* @author schukai GmbH
*/
import {Monster} from '../namespace.js';
import {TokenList} from '../types/tokenlist.js';
import {isObject} from '../types/is.js';
import '../types/object.js';
/**
* an observer manages a callback function
*
* you can call the method via the monster namespace `new Monster.Types.Observer()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.3.0/dist/modules/types/observer.js';
* console.log(new Monster.Types.Observer())
* </script>
* ```
*
* Alternatively, you can also integrate this function individually.
*
* ```
* <script type="module">
* import {Observer} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.3.0/dist/modules/types/observer.js';
* console.log(Observer())
* </script>
* ```
*
* the update method is called with the subject object as this pointer. for this reason the callback should not
* be an arrow function, because it gets the this pointer of its own context.
*
* ```
* <script>
* Observer(()=>{
* // this is not subject
* })
*
* Observer(function() {
* // this is subject
* })
* </script>
* ```
*
* additional arguments can be passed to the callback. to do this, simply specify them.
*
* ```
* <script>
* Observer(function(a, b, c) {
* console.log(a, b, c); // ↦ "a", 2, true
* }, "a", 2, true)
* </script>
* ```
*
* the callback function must have as many parameters as arguments are given.
*
*
* @since 1.0.0
* @copyright schukai GmbH
* @memberOf Monster/Types
*/
class Observer extends Monster.Types.Object {
/**
*
* @param {function} callback
* @param {*} args
*/
constructor(callback, ...args) {
super();
if (typeof callback !== 'function') {
throw new Error("observer callback must be a function")
}
this.callback = callback;
this.arguments = args;
this.tags = new TokenList;
}
/**
*
* @param {string} tag
* @returns {Observer}
*/
addTag(tag) {
this.tags.add(tag);
return this;
}
/**
*
* @param {string} tag
* @returns {Observer}
*/
removeTag(tag) {
this.tags.remove(tag);
return this;
}
/**
*
* @returns {Array}
*/
getTags() {
return this.tags.entries()
}
/**
*
* @param {string} tag
* @returns {boolean}
*/
hasTag(tag) {
return this.tags.contains(tag)
}
/**
*
* @param {object} subject
* @returns {Promise}
*/
update(subject) {
let self = this;
return new Promise(function (resolve, reject) {
if (!isObject(subject)) {
reject("subject must be an object");
}
let result = self.callback.apply(subject, self.arguments);
resolve(result);
});
};
}
Monster.assignToNamespace('Monster.Types', Observer);
export {Monster, Observer}