import Utils from "../helpers/utils";
import {moduleS, subscriptions, eventQ} from "./store.js";
/**
* @class
*
*/
class PubSub {
/**
* Subscribes to the truss event
* @param subscription {Object} the subscription object
* @param [eventName = subscription.eventName]
*/
subscribe (subscription, eventName = subscription.eventName) {
if (!subscriptions[eventName]) subscriptions[eventName] = [];
let subscriptionData = Utils.pick(subscription, ['callback', 'context', 'eventSubscriber', 'eventPublisher', 'once', 'type']);
subscriptions[eventName].push(subscriptionData);
};
/**
* Publishes a truss event
* @param eventName {string}
* @param message {string}
*/
publish(eventName, message) {
let publisher = "";
if(arguments.length === 3){
publisher = arguments[0] || "";
eventName = arguments[1];
message = arguments[2];
} else {
publisher = Utils.getCSSSelector(this);
}
var subscriptionsForEvent = subscriptions[eventName],
remainingSubscriptions = [];
if(!subscriptionsForEvent){
return;
}
// If any of the subscription is of type Replay
// Push the message to eventQ
let replaySubscriptions = subscriptionsForEvent.filter((subs)=> {
if (subs.type === "RE_PLAY") return subs;
});
if (replaySubscriptions.length) eventQ.store.push({
eventName,
message,
publisher
});
subscriptionsForEvent && subscriptionsForEvent.length && subscriptionsForEvent.forEach(function (subscription) {
let callback = subscription.callback,
context = subscription.context,
subscribeOnce = subscription.once,
subscriptionMatched = false;
if (subscription.eventPublisher) {
let regex = new RegExp(subscription.eventPublisher + "$");
if (regex.test(publisher)) {
subscriptionMatched = true;
} else {
let actualPublisherHierarchy = publisher.split(' '),
subscriptionPublisherHierarhcy = subscription.eventPublisher.split(' '),
actualPublisherHierarchyLength = actualPublisherHierarchy.length,
subscriptionPublisherHierarhcyLength = subscriptionPublisherHierarhcy.length;
while (actualPublisherHierarchy.length && subscriptionPublisherHierarhcy.length) {
actualPublisherHierarchyLength = actualPublisherHierarchy.length;
subscriptionPublisherHierarhcyLength = subscriptionPublisherHierarhcy.length;
if (actualPublisherHierarchy[actualPublisherHierarchyLength - 1] === subscriptionPublisherHierarhcy[subscriptionPublisherHierarhcyLength - 1]) {
actualPublisherHierarchy.pop();
subscriptionPublisherHierarhcy.pop();
} else {
actualPublisherHierarchy.pop();
}
}
if (!subscriptionPublisherHierarhcy.length) {
subscriptionMatched = true;
}
}
}
if (!subscription.eventPublisher || subscriptionMatched) {
// If replay event: publish only after render is complete
// If replay event: publish all the data matched from event queue
let publishData = message;
if (subscription.type === "RE_PLAY") {
publishData = eventQ.store.filter((evt)=> {
if (evt.publisher === publisher && evt.eventName === eventName) {
return evt;
}
}).map((evt)=> {
return evt.message;
});
}
callback.call((context ? context : null), publishData);
if (!subscribeOnce) {
remainingSubscriptions.push(subscription);
}
} else {
remainingSubscriptions.push(subscription);
}
});
subscriptions[eventName] = remainingSubscriptions;
};
/**
* unsubscribes a truss event
* @param subscriber {Object} the reference of the module which had subscribed the event earlier
* @param eventName {string}
* @param callback {function} the callback method to be unsubscribed
*/
unsubscribe(subscriber, eventName, callback) {
var subscriptionsForEvent = subscriptions[eventName];
if(!subscriptionsForEvent) {
return;
}
// Check if any RE_PLAY event is there and all the event context is of is same as
// destroy its data from eventQ
let replaySubscriptions = subscriptionsForEvent.filter((subscription)=>{
if(subscription.type === "RE_PLAY") return subscription;
});
subscriptions[eventName] = subscriptionsForEvent.filter(function (subscription) {
return !(subscription.callback === callback && subscription.eventSubscriber === subscriber);
});
if(replaySubscriptions.length){
if(!subscriptions[eventName].length) {
// Remove all the items from eventQ with eventName
eventQ.store = eventQ.store.filter((evt)=>{
if(evt.eventName !== eventName) return evt;
})
}
}
};
}
export default PubSub;