'use strict';

var _keys = require('babel-runtime/core-js/object/keys');

var _keys2 = _interopRequireDefault(_keys);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var util = require('../util');

var Emitter = function () {
  function Emitter() {
    (0, _classCallCheck3.default)(this, Emitter);

    this._eventHandler = {};
  }

  (0, _createClass3.default)(Emitter, [{
    key: 'on',
    value: function on(event, namespace, handler) {
      if (arguments.length === 2) {
        handler = namespace;
        namespace = '';
      }
      if (!this._eventHandler[event]) {
        this._eventHandler[event] = {};
      }

      var target = util.objectLocate(this._eventHandler[event], namespace);

      if (target.__handlers__) {
        target.__handlers__.push(handler);
      } else {
        target.__handlers__ = [handler];
      }
    }
  }, {
    key: 'off',
    value: function off(event, namespace) {
      if (this._eventHandler[event]) {
        if (!namespace) {
          this._eventHandler[event] = {};
        } else {
          util.clearObjectAt(this._eventHandler[event], namespace);
        }
      }
    }
  }, {
    key: 'emit',
    value: function emit(event, namespace, data) {
      if (arguments.length === 2) {
        data = namespace;
        namespace = '';
      }
      if (this._eventHandler[event]) {
        var context = {
          namespace: namespace,
          event: event,
          path: namespace
        };
        return this._emit(this._eventHandler[event], namespace, context, data);
      } else {
        return false;
      }
    }
  }, {
    key: '_emit',
    value: function _emit(prevTarget, namespace, context, data) {
      context.path = namespace;
      var target = util.objectGet(prevTarget, namespace);
      if (target && target.__handlers__) {
        target.__handlers__.forEach(function (h) {
          return h.call(context, data);
        });
      } else {
        if (namespace) {
          var ns = namespace.substr(0, namespace.lastIndexOf('.'));
          return this._emit(prevTarget, ns, context, data);
        } else {
          return false;
        }
      }
    }
  }, {
    key: 'broadcast',
    value: function broadcast(event, namespace, data) {
      if (arguments.length === 2) {
        data = namespace;
        namespace = '';
      }
      if (this._eventHandler[event]) {
        var target = util.objectGet(this._eventHandler[event], namespace);
        if (target) {
          var context = { event: event, namespace: namespace, path: namespace };
          this._broadcast(target, context, data);
          return true;
        } else return false;
      } else {
        return false;
      }
    }
  }, {
    key: '_broadcast',
    value: function _broadcast(target, context, data) {
      var _this = this;

      target.__handlers__ && target.__handlers__.forEach(function (h) {
        return h.call(context, data);
      });
      var keys = (0, _keys2.default)(target).filter(function (k) {
        return k !== '__handlers__';
      });

      keys.forEach(function (k) {
        var ctx = { event: context.event, namespace: context.namespace, path: context.namespace + '.' + k };
        _this._broadcast(target[k], ctx, data);
      });
    }
  }]);
  return Emitter;
}();

module.exports = Emitter;