"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const index_esm$1 = require("../../../../min-dash/dist/index.esm.js");
const index_esm = require("../../../../min-dom/dist/index.esm.js");
const KeyboardUtil = require("./KeyboardUtil.js");
var KEYDOWN_EVENT = "keyboard.keydown", KEYUP_EVENT = "keyboard.keyup";
var HANDLE_MODIFIER_ATTRIBUTE = "input-handle-modified-keys";
var DEFAULT_PRIORITY = 1e3;
function Keyboard(config, eventBus) {
  var self = this;
  this._config = config || {};
  this._eventBus = eventBus;
  this._keydownHandler = this._keydownHandler.bind(this);
  this._keyupHandler = this._keyupHandler.bind(this);
  eventBus.on("diagram.destroy", function() {
    self._fire("destroy");
    self.unbind();
  });
  eventBus.on("diagram.init", function() {
    self._fire("init");
  });
  eventBus.on("attach", function() {
    if (config && config.bindTo) {
      self.bind(config.bindTo);
    }
  });
  eventBus.on("detach", function() {
    self.unbind();
  });
}
Keyboard.$inject = [
  "config.keyboard",
  "eventBus"
];
Keyboard.prototype._keydownHandler = function(event) {
  this._keyHandler(event, KEYDOWN_EVENT);
};
Keyboard.prototype._keyupHandler = function(event) {
  this._keyHandler(event, KEYUP_EVENT);
};
Keyboard.prototype._keyHandler = function(event, type) {
  var eventBusResult;
  if (this._isEventIgnored(event)) {
    return;
  }
  var context = {
    keyEvent: event
  };
  eventBusResult = this._eventBus.fire(type || KEYDOWN_EVENT, context);
  if (eventBusResult) {
    event.preventDefault();
  }
};
Keyboard.prototype._isEventIgnored = function(event) {
  return isInput(event.target) && this._isModifiedKeyIgnored(event);
};
Keyboard.prototype._isModifiedKeyIgnored = function(event) {
  if (!KeyboardUtil.isCmd(event)) {
    return true;
  }
  var allowedModifiers = this._getAllowedModifiers(event.target);
  return allowedModifiers.indexOf(event.key) === -1;
};
Keyboard.prototype._getAllowedModifiers = function(element) {
  var modifierContainer = index_esm.closest(element, "[" + HANDLE_MODIFIER_ATTRIBUTE + "]", true);
  if (!modifierContainer || this._node && !this._node.contains(modifierContainer)) {
    return [];
  }
  return modifierContainer.getAttribute(HANDLE_MODIFIER_ATTRIBUTE).split(",");
};
Keyboard.prototype.bind = function(node) {
  this.unbind();
  this._node = node;
  index_esm.event.bind(node, "keydown", this._keydownHandler, true);
  index_esm.event.bind(node, "keyup", this._keyupHandler, true);
  this._fire("bind");
};
Keyboard.prototype.getBinding = function() {
  return this._node;
};
Keyboard.prototype.unbind = function() {
  var node = this._node;
  if (node) {
    this._fire("unbind");
    index_esm.event.unbind(node, "keydown", this._keydownHandler, true);
    index_esm.event.unbind(node, "keyup", this._keyupHandler, true);
  }
  this._node = null;
};
Keyboard.prototype._fire = function(event) {
  this._eventBus.fire("keyboard." + event, { node: this._node });
};
Keyboard.prototype.addListener = function(priority, listener, type) {
  if (index_esm$1.isFunction(priority)) {
    type = listener;
    listener = priority;
    priority = DEFAULT_PRIORITY;
  }
  this._eventBus.on(type || KEYDOWN_EVENT, priority, listener);
};
Keyboard.prototype.removeListener = function(listener, type) {
  this._eventBus.off(type || KEYDOWN_EVENT, listener);
};
Keyboard.prototype.hasModifier = KeyboardUtil.hasModifier;
Keyboard.prototype.isCmd = KeyboardUtil.isCmd;
Keyboard.prototype.isShift = KeyboardUtil.isShift;
Keyboard.prototype.isKey = KeyboardUtil.isKey;
function isInput(target) {
  return target && (index_esm.matches(target, "input, textarea") || target.contentEditable === "true");
}
exports.default = Keyboard;
