// Generated by CoffeeScript 1.12.7
(function() {
  var Mode, SuppressAllKeyboardEvents, count, root,
    slice = [].slice,
    extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;

  count = 0;

  Mode = (function() {
    Mode.debug = false;

    Mode.modes = [];

    Mode.prototype.continueBubbling = handlerStack.continueBubbling;

    Mode.prototype.suppressEvent = handlerStack.suppressEvent;

    Mode.prototype.passEventToPage = handlerStack.passEventToPage;

    Mode.prototype.suppressPropagation = handlerStack.suppressPropagation;

    Mode.prototype.restartBubbling = handlerStack.restartBubbling;

    Mode.prototype.alwaysContinueBubbling = handlerStack.alwaysContinueBubbling;

    Mode.prototype.alwaysSuppressPropagation = handlerStack.alwaysSuppressPropagation;

    function Mode(options1) {
      var fn, i, key, len, ref, ref1, singletons, type;
      this.options = options1 != null ? options1 : {};
      this.handlers = [];
      this.exitHandlers = [];
      this.modeIsActive = true;
      this.modeIsExiting = false;
      this.name = this.options.name || "anonymous";
      this.count = ++count;
      this.id = this.name + "-" + this.count;
      this.log("activate:", this.id);
      if (this.options.suppressAllKeyboardEvents) {
        ref = ["keydown", "keypress", "keyup"];
        fn = (function(_this) {
          return function(handler) {
            return _this.options[type] = function(event) {
              return _this.alwaysSuppressPropagation(function() {
                return typeof handler === "function" ? handler(event) : void 0;
              });
            };
          };
        })(this);
        for (i = 0, len = ref.length; i < len; i++) {
          type = ref[i];
          fn(this.options[type]);
        }
      }
      this.push({
        keydown: this.options.keydown || null,
        keypress: this.options.keypress || null,
        keyup: this.options.keyup || null,
        indicator: (function(_this) {
          return function() {
            if (_this.options.indicator != null) {
              if (_this.options.indicator) {
                HUD.show(_this.options.indicator);
              } else {
                HUD.hide(true, false);
              }
              return _this.passEventToPage;
            } else {
              return _this.continueBubbling;
            }
          };
        })(this)
      });
      if (this.options.exitOnEscape) {
        this.push({
          _name: "mode-" + this.id + "/exitOnEscape",
          "keydown": (function(_this) {
            return function(event) {
              if (!KeyboardUtils.isEscape(event)) {
                return _this.continueBubbling;
              }
              _this.exit(event, event.target);
              return DomUtils.consumeKeyup(event);
            };
          })(this)
        });
      }
      if (this.options.exitOnBlur) {
        this.push({
          _name: "mode-" + this.id + "/exitOnBlur",
          "blur": (function(_this) {
            return function(event) {
              return _this.alwaysContinueBubbling(function() {
                if (event.target === _this.options.exitOnBlur) {
                  return _this.exit(event);
                }
              });
            };
          })(this)
        });
      }
      if (this.options.exitOnClick) {
        this.push({
          _name: "mode-" + this.id + "/exitOnClick",
          "click": (function(_this) {
            return function(event) {
              return _this.alwaysContinueBubbling(function() {
                return _this.exit(event);
              });
            };
          })(this)
        });
      }
      if (this.options.exitOnFocus) {
        this.push({
          _name: "mode-" + this.id + "/exitOnFocus",
          "focus": (function(_this) {
            return function(event) {
              return _this.alwaysContinueBubbling(function() {
                if (DomUtils.isFocusable(event.target)) {
                  return _this.exit(event);
                }
              });
            };
          })(this)
        });
      }
      if (this.options.exitOnScroll) {
        this.push({
          _name: "mode-" + this.id + "/exitOnScroll",
          "scroll": (function(_this) {
            return function(event) {
              return _this.alwaysContinueBubbling(function() {
                return _this.exit(event);
              });
            };
          })(this)
        });
      }
      if (this.options.singleton) {
        singletons = Mode.singletons || (Mode.singletons = {});
        key = this.options.singleton;
        this.onExit(function() {
          return delete singletons[key];
        });
        if ((ref1 = singletons[key]) != null) {
          ref1.exit();
        }
        singletons[key] = this;
      }
      if (this.options.passInitialKeyupEvents) {
        this.push({
          _name: "mode-" + this.id + "/passInitialKeyupEvents",
          keydown: (function(_this) {
            return function() {
              return _this.alwaysContinueBubbling(function() {
                return handlerStack.remove();
              });
            };
          })(this),
          keyup: (function(_this) {
            return function(event) {
              if (KeyboardUtils.isPrintable(event)) {
                return _this.suppressPropagation;
              } else {
                return _this.passEventToPage;
              }
            };
          })(this)
        });
      }
      if (this.options.suppressTrailingKeyEvents) {
        this.onExit(function() {
          var handler, keyEventSuppressor;
          handler = function(event) {
            if (event.repeat) {
              return handlerStack.suppressEvent;
            } else {
              keyEventSuppressor.exit();
              return handlerStack.continueBubbling;
            }
          };
          return keyEventSuppressor = new Mode({
            name: "suppress-trailing-key-events",
            keydown: handler,
            keypress: handler,
            keyup: function() {
              return handlerStack.suppressPropagation;
            }
          });
        });
      }
      Mode.modes.push(this);
      this.setIndicator();
      this.logModes();
    }

    Mode.prototype.setIndicator = function(indicator) {
      if (indicator == null) {
        indicator = this.options.indicator;
      }
      this.options.indicator = indicator;
      return Mode.setIndicator();
    };

    Mode.setIndicator = function() {
      return handlerStack.bubbleEvent("indicator");
    };

    Mode.prototype.push = function(handlers) {
      handlers._name || (handlers._name = "mode-" + this.id);
      return this.handlers.push(handlerStack.push(handlers));
    };

    Mode.prototype.unshift = function(handlers) {
      handlers._name || (handlers._name = "mode-" + this.id);
      return this.handlers.push(handlerStack.unshift(handlers));
    };

    Mode.prototype.onExit = function(handler) {
      return this.exitHandlers.push(handler);
    };

    Mode.prototype.exit = function() {
      var args, handler, handlerId, i, j, len, len1, ref, ref1;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      if (this.modeIsExiting || !this.modeIsActive) {
        return;
      }
      this.log("deactivate:", this.id);
      this.modeIsExiting = true;
      ref = this.exitHandlers;
      for (i = 0, len = ref.length; i < len; i++) {
        handler = ref[i];
        handler.apply(null, args);
      }
      ref1 = this.handlers;
      for (j = 0, len1 = ref1.length; j < len1; j++) {
        handlerId = ref1[j];
        handlerStack.remove(handlerId);
      }
      Mode.modes = Mode.modes.filter((function(_this) {
        return function(mode) {
          return mode !== _this;
        };
      })(this));
      this.modeIsActive = false;
      return this.setIndicator();
    };

    Mode.prototype.logModes = function() {
      var i, len, mode, ref, results;
      if (Mode.debug) {
        this.log("active modes (top to bottom):");
        ref = Mode.modes.slice(0).reverse();
        results = [];
        for (i = 0, len = ref.length; i < len; i++) {
          mode = ref[i];
          results.push(this.log(" ", mode.id));
        }
        return results;
      }
    };

    Mode.prototype.log = function() {
      var args;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      if (Mode.debug) {
        return console.log.apply(console, args);
      }
    };

    Mode.top = function() {
      return this.modes[this.modes.length - 1];
    };

    Mode.reset = function() {
      var i, len, mode, ref;
      ref = this.modes;
      for (i = 0, len = ref.length; i < len; i++) {
        mode = ref[i];
        mode.exit();
      }
      return this.modes = [];
    };

    return Mode;

  })();

  SuppressAllKeyboardEvents = (function(superClass) {
    extend1(SuppressAllKeyboardEvents, superClass);

    function SuppressAllKeyboardEvents(options) {
      var defaults;
      if (options == null) {
        options = {};
      }
      defaults = {
        name: "suppressAllKeyboardEvents",
        suppressAllKeyboardEvents: true
      };
      SuppressAllKeyboardEvents.__super__.constructor.call(this, extend(defaults, options));
    }

    return SuppressAllKeyboardEvents;

  })(Mode);

  root = typeof exports !== "undefined" && exports !== null ? exports : window;

  extend(root, {
    Mode: Mode,
    SuppressAllKeyboardEvents: SuppressAllKeyboardEvents
  });

}).call(this);
