var MultiTargetEventDispatcher = (function(bjUtil, logger) {
	if (!bjUtil) {
		throw 'BJUtil instance not found!';
	}

	function MultiTargetEventDispatcher() {
		this.targets = {};
		this.targetEventHandlers = {};
	}

	MultiTargetEventDispatcher.prototype.registerTarget = function(name, element) {
		this.targets[name] = element;
		this.targetEventHandlers[name] = {};
	};

	MultiTargetEventDispatcher.prototype.registerEventTrigger = function(targetName, eventName) {
		var self = this;
		var target = bjUtil.idx(this.targets, targetName);
		if (target) {
			var targetEvents = bjUtil.idx(this.targetEventHandlers, targetName);
			if (!targetEvents) {
				logger.error('Target - {0} is not registered.'.f(targetName));
			} else {
				if (target instanceof jQuery) {
					target.on(eventName, function(e) {
						self.trigger(targetName, eventName, e, this);
					});
				} else if (typeof(target) == 'string') {
					$('body').on(eventName, target, function(e) {
						self.trigger(targetName, eventName, e, this);
					});
				}
				targetEvents[eventName] = [];
			}
		}
	};

	/**
	 * @param targetName
	 * @param eventName
	 * @param callback [function($target, event)]
	 */
	MultiTargetEventDispatcher.prototype.on = function(targetName, eventName, callback) {
		var targetEvents = bjUtil.idx(this.targetEventHandlers, targetName);
		if (!targetEvents) {
			logger.error('Target - {0} is not registered.'.f(targetName));
			return;
		}
		var eventCallbacks = BJUtil.idx(targetEvents, eventName);
		if (!eventCallbacks) {
			logger.error('{0} does not respond to event - {1}'.f(targetName, eventName));
			return;
		}

		eventCallbacks.push(callback);
		targetEvents[eventName] = eventCallbacks;
		this.targetEventHandlers[targetName] = targetEvents;
	};

	MultiTargetEventDispatcher.prototype.trigger = function(targetName, eventName, event, target) {
		event.stopImmediatePropagation();
		var targetEvents = bjUtil.idx(this.targetEventHandlers, targetName, {});
		var eventCallbacks = bjUtil.idx(targetEvents, eventName, []);

		eventCallbacks.forEach(function(callback) {
			callback(target, event);
		});
	};

	return MultiTargetEventDispatcher;
})(BJUtil, console);