(function () {
  "use strict";

  Class('signals.PromiseSignal', { Extends: signals.Signal,

    _originalDispatchMethod: null,

    /**
     *
     * @class signals.PromiseSignal
     *
     * @classdesc
     * PromiseSignal extends the Signal class to return a new promise
     * for every dispatch call. The promise *fulfill* and *reject* methods
     * are given to all signal listeners so that any listener can fulfill
     * or reject the promise.
     *
     * This is pretty awesome for decoupled systems that talk via signals
     * and commands. With the promises there is now an informal approach
     * for a command to give an answer about the result of the operation.
     *
     * The code that dispatches the signal (and possibly triggers some
     * other action somewhere in the system) often wants to know if the
     * triggered operation was successful or not.
     *
     * @initialize
     * The PromiseSignal constructor does not take any parameters.
     *
     * @example
     * <caption>
     *   <h4>Creating and Using a PromiseSignal</h4>
     *   This example shows how to setup a PromiseSignal
     *   that has one listener which fulfills the promise
     *   immediately. The fulfillment listener is invoked
     *   because it was registered as first argument to the
     *   dispatch(…).then() method of the promise.
     * </caption>
     *
     * var promiseSignal = new signals.PromiseSignal(),
     *     fulfillData = {},
     *     dispatchData = {};
     *
     * function signalListener(data, promise) {
     *
     *    expect.equal(data, dispatchData, 'Expected to receive dispatched data')
     *
     *    // here the listener fulfills the promise!
     *    promise.fulfill(fulfillData);
     * }
     *
     * // when the listener fulfills the promise this function is called
     * function promiseFulfilledListener(data) {
     *    expect.equal(data, fulfillData, 'Expected fulfill data');
     * }
     *
     * promiseSignal.add(signalListener);
     * promiseSignal.dispatch(dispatchData).then(promiseFulfilledListener);
     *
     * @memberof! <global>
     */

    Constructor: function() {

      // let super class construct this signal
      this.Class.Super.apply(this, arguments);

      // save reference to original dispatch of signals.Signal
      this._originalDispatchMethod = this.dispatch;

      // replace the original dispatch method by our wrapper
      this.dispatch = this.Class.prototype.dispatch;
    },

    /**
     * Dispatches the signal like the base class but returns
     * a new promise object and provides all listeners with
     * the promise *fulfill* and *reject* functions.
     *
     * @param {*} any data that should be dispatched to the listeners
     *
     * @returns {Promise} A Promise A/+ instance
     *
     * @memberof signals.PromiseSignal#
     */

    dispatch: function() {

      var argumentsArray = Array.prototype.slice.call(arguments),
          This = this;

      return new Promise(function(fulfill, reject) {

        if(This.getNumListeners() == 0) {
          fulfill();
        }
        else {

          argumentsArray.push({
            fulfill: fulfill,
            reject: reject
          });

          // call the original dispatch method with the promise
          This._originalDispatchMethod.apply(This, argumentsArray);
        }

      });

    }

  });

}());