AMapUI.define([ "lib/utils" ], function(utils) {
  "use strict";
  function Event() {
      this.__evHash = {};
  }
  utils.extend(Event.prototype, {
      on: function(ev, listener, priority) {
          if (this.__multiCall(ev, listener, this.on)) return this;
          if (!ev) return this;
          var evHash = this.__evHash;
          evHash[ev] || (evHash[ev] = []);
          var list = evHash[ev], index = this.__index(list, listener);
          if (index < 0) {
              "number" != typeof priority && (priority = 10);
              for (var inps = list.length, i = 0, len = list.length; i < len; i++) if (priority > list[i].priority) {
                  inps = i;
                  break;
              }
              list.splice(inps, 0, {
                  listener: listener,
                  priority: priority
              });
          }
          return this;
      },
      once: function(ev, listener, priority) {
          function oncefunc() {
              self.__callListenser(listener, arguments);
              self.off(ev, oncefunc);
          }
          if (this.__multiCall(ev, listener, this.once)) return this;
          var self = this;
          this.on(ev, oncefunc, priority);
          return this;
      },
      offAll: function() {
          for (var ev in this.__evHash) this.off(ev);
          this.__evHash = {};
          return this;
      },
      off: function(ev, listener) {
          if (this.__multiCall(ev, listener, this.off)) return this;
          var evHash = this.__evHash;
          if (evHash[ev]) {
              var list = evHash[ev];
              if ("undefined" == typeof listener) {
                  var c = list.length;
                  list.length = 0;
                  return c;
              }
              var index = this.__index(list, listener);
              if (index >= 0) {
                  list.splice(index, 1);
                  return 1;
              }
              return 0;
          }
      },
      listenerLength: function(ev) {
          var evHash = this.__evHash, list = evHash[ev];
          return list ? list.length : 0;
      },
      emit: function(ev) {
          var args, list, evHash = this.__evHash, count = 0;
          list = evHash[ev];
          if (list && list.length) {
              args = Array.prototype.slice.call(arguments, 1);
              count += this.__callListenerList(list, args);
          }
          list = evHash["*"];
          if (list && list.length) {
              args = Array.prototype.slice.call(arguments);
              count += this.__callListenerList(list, args);
          }
          return count;
      },
      trigger: function(ev) {
          var args = Array.prototype.slice.call(arguments, 0);
          args.splice(1, 0, {
              type: ev,
              target: this
          });
          this.emit.apply(this, args);
      },
      triggerWithOriginalEvent: function(ev, originalEvent) {
          var args = Array.prototype.slice.call(arguments, 0);
          args[1] = {
              type: ev,
              target: originalEvent ? originalEvent.target : this,
              originalEvent: originalEvent
          };
          this.emit.apply(this, args);
      },
      onDestroy: function(cb, priority) {
          this.on("__destroy", cb, priority);
          return this;
      },
      destroy: function() {
          if (!this.__destroying) {
              this.__destroying = 1;
              this.emit("__destroy", this);
              this.offAll();
              return this;
          }
      },
      __multiCall: function(ev, listener, func) {
          if (!ev) return !0;
          if (utils.isObject(ev) && "undefined" == typeof listener) {
              for (var k in ev) func.call(this, k, ev[k]);
              return !0;
          }
          var evs;
          utils.isArray(ev) ? evs = ev : "string" == typeof ev && (evs = ev.split(/[\s,]+/));
          if (evs && evs.length > 1) {
              for (var i = 0, len = evs.length; i < len; i++) evs[i] && func.call(this, evs[i], listener);
              return !0;
          }
          return !1;
      },
      __index: function(list, listener) {
          for (var index = -1, i = 0, len = list.length; i < len; i++) {
              var ele = list[i];
              if (ele.listener === listener) {
                  index = i;
                  break;
              }
          }
          return index;
      },
      __callListenser: function(listener, args) {
          var func = null, contxt = null;
          if ("function" == typeof listener) {
              func = listener;
              contxt = this;
          } else if (2 == listener.length) {
              func = listener[1];
              contxt = listener[0];
          }
          return func ? [ 1, func.apply(contxt, args) ] : [ 0, void 0 ];
      },
      __callListenerList: function(list, args) {
          if (!list || !list.length) return 0;
          list = [].concat(list);
          for (var cres, count = 0, i = 0, len = list.length; i < len; i++) {
              cres = this.__callListenser(list[i].listener, args);
              count += cres[0];
              if (cres[1] === !1) break;
          }
          return count;
      }
  });
  return Event;
});