import { isFunction } from "../../../../min-dash/dist/index.esm.mjs";
import { closest, event, matches } from "../../../../min-dom/dist/index.esm.mjs";
import { isCmd, hasModifier, isShift, isKey } from "./KeyboardUtil.mjs";
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(event2) {
  this._keyHandler(event2, KEYDOWN_EVENT);
};
Keyboard.prototype._keyupHandler = function(event2) {
  this._keyHandler(event2, KEYUP_EVENT);
};
Keyboard.prototype._keyHandler = function(event2, type) {
  var eventBusResult;
  if (this._isEventIgnored(event2)) {
    return;
  }
  var context = {
    keyEvent: event2
  };
  eventBusResult = this._eventBus.fire(type || KEYDOWN_EVENT, context);
  if (eventBusResult) {
    event2.preventDefault();
  }
};
Keyboard.prototype._isEventIgnored = function(event2) {
  return isInput(event2.target) && this._isModifiedKeyIgnored(event2);
};
Keyboard.prototype._isModifiedKeyIgnored = function(event2) {
  if (!isCmd(event2)) {
    return true;
  }
  var allowedModifiers = this._getAllowedModifiers(event2.target);
  return allowedModifiers.indexOf(event2.key) === -1;
};
Keyboard.prototype._getAllowedModifiers = function(element) {
  var modifierContainer = 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;
  event.bind(node, "keydown", this._keydownHandler, true);
  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");
    event.unbind(node, "keydown", this._keydownHandler, true);
    event.unbind(node, "keyup", this._keyupHandler, true);
  }
  this._node = null;
};
Keyboard.prototype._fire = function(event2) {
  this._eventBus.fire("keyboard." + event2, { node: this._node });
};
Keyboard.prototype.addListener = function(priority, listener, type) {
  if (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 = hasModifier;
Keyboard.prototype.isCmd = isCmd;
Keyboard.prototype.isShift = isShift;
Keyboard.prototype.isKey = isKey;
function isInput(target) {
  return target && (matches(target, "input, textarea") || target.contentEditable === "true");
}
export {
  Keyboard as default
};
