"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const index_esm = require("../../../../min-dash/dist/index.esm.js");
const index_esm$1 = require("../../../../min-dom/dist/index.esm.js");
const Mouse = require("../../util/Mouse.js");
const index_esm$2 = require("../../../../tiny-svg/dist/index.esm.js");
const RenderUtil = require("../../util/RenderUtil.js");
function allowAll(event) {
  return true;
}
function allowPrimaryAndAuxiliary(event) {
  return Mouse.isPrimaryButton(event) || Mouse.isAuxiliaryButton(event);
}
var LOW_PRIORITY = 500;
function InteractionEvents(eventBus, elementRegistry, styles) {
  var self = this;
  function fire(type, event, element) {
    if (isIgnored(type, event)) {
      return;
    }
    var target, gfx, returnValue;
    if (!element) {
      target = event.delegateTarget || event.target;
      if (target) {
        gfx = target;
        element = elementRegistry.get(gfx);
      }
    } else {
      gfx = elementRegistry.getGraphics(element);
    }
    if (!gfx || !element) {
      return;
    }
    returnValue = eventBus.fire(type, {
      element,
      gfx,
      originalEvent: event
    });
    if (returnValue === false) {
      event.stopPropagation();
      event.preventDefault();
    }
  }
  var handlers = {};
  function mouseHandler(localEventName) {
    return handlers[localEventName];
  }
  function isIgnored(localEventName, event) {
    var filter = ignoredFilters[localEventName] || Mouse.isPrimaryButton;
    return !filter(event);
  }
  var bindings = {
    click: "element.click",
    contextmenu: "element.contextmenu",
    dblclick: "element.dblclick",
    mousedown: "element.mousedown",
    mousemove: "element.mousemove",
    mouseover: "element.hover",
    mouseout: "element.out",
    mouseup: "element.mouseup"
  };
  var ignoredFilters = {
    "element.contextmenu": allowAll,
    "element.mousedown": allowPrimaryAndAuxiliary,
    "element.mouseup": allowPrimaryAndAuxiliary,
    "element.click": allowPrimaryAndAuxiliary,
    "element.dblclick": allowPrimaryAndAuxiliary
  };
  function triggerMouseEvent(eventName, event, targetElement) {
    var localEventName = bindings[eventName];
    if (!localEventName) {
      throw new Error("unmapped DOM event name <" + eventName + ">");
    }
    return fire(localEventName, event, targetElement);
  }
  var ELEMENT_SELECTOR = "svg, .djs-element";
  function registerEvent(node, event, localEvent, ignoredFilter) {
    var handler = handlers[localEvent] = function(event2) {
      fire(localEvent, event2);
    };
    if (ignoredFilter) {
      ignoredFilters[localEvent] = ignoredFilter;
    }
    handler.$delegate = index_esm$1.delegate.bind(node, ELEMENT_SELECTOR, event, handler);
  }
  function unregisterEvent(node, event, localEvent) {
    var handler = mouseHandler(localEvent);
    if (!handler) {
      return;
    }
    index_esm$1.delegate.unbind(node, event, handler.$delegate);
  }
  function registerEvents(svg) {
    index_esm.forEach(bindings, function(val, key) {
      registerEvent(svg, key, val);
    });
  }
  function unregisterEvents(svg) {
    index_esm.forEach(bindings, function(val, key) {
      unregisterEvent(svg, key, val);
    });
  }
  eventBus.on("canvas.destroy", function(event) {
    unregisterEvents(event.svg);
  });
  eventBus.on("canvas.init", function(event) {
    registerEvents(event.svg);
  });
  eventBus.on(["shape.added", "connection.added"], function(event) {
    var element = event.element, gfx = event.gfx;
    eventBus.fire("interactionEvents.createHit", { element, gfx });
  });
  eventBus.on([
    "shape.changed",
    "connection.changed"
  ], LOW_PRIORITY, function(event) {
    var element = event.element, gfx = event.gfx;
    eventBus.fire("interactionEvents.updateHit", { element, gfx });
  });
  eventBus.on("interactionEvents.createHit", LOW_PRIORITY, function(event) {
    var element = event.element, gfx = event.gfx;
    self.createDefaultHit(element, gfx);
  });
  eventBus.on("interactionEvents.updateHit", function(event) {
    var element = event.element, gfx = event.gfx;
    self.updateDefaultHit(element, gfx);
  });
  var STROKE_HIT_STYLE = createHitStyle("djs-hit djs-hit-stroke");
  var CLICK_STROKE_HIT_STYLE = createHitStyle("djs-hit djs-hit-click-stroke");
  var ALL_HIT_STYLE = createHitStyle("djs-hit djs-hit-all");
  var NO_MOVE_HIT_STYLE = createHitStyle("djs-hit djs-hit-no-move");
  var HIT_TYPES = {
    "all": ALL_HIT_STYLE,
    "click-stroke": CLICK_STROKE_HIT_STYLE,
    "stroke": STROKE_HIT_STYLE,
    "no-move": NO_MOVE_HIT_STYLE
  };
  function createHitStyle(classNames, attrs) {
    attrs = index_esm.assign({
      stroke: "white",
      strokeWidth: 15
    }, attrs || {});
    return styles.cls(classNames, ["no-fill", "no-border"], attrs);
  }
  function applyStyle(hit, type) {
    var attrs = HIT_TYPES[type];
    if (!attrs) {
      throw new Error("invalid hit type <" + type + ">");
    }
    index_esm$2.attr(hit, attrs);
    return hit;
  }
  function appendHit(gfx, hit) {
    index_esm$2.append(gfx, hit);
  }
  this.removeHits = function(gfx) {
    var hits = index_esm$1.queryAll(".djs-hit", gfx);
    index_esm.forEach(hits, index_esm$2.remove);
  };
  this.createDefaultHit = function(element, gfx) {
    var waypoints = element.waypoints, isFrame = element.isFrame, boxType;
    if (waypoints) {
      return this.createWaypointsHit(gfx, waypoints);
    } else {
      boxType = isFrame ? "stroke" : "all";
      return this.createBoxHit(gfx, boxType, {
        width: element.width,
        height: element.height
      });
    }
  };
  this.createWaypointsHit = function(gfx, waypoints) {
    var hit = RenderUtil.createLine(waypoints);
    applyStyle(hit, "stroke");
    appendHit(gfx, hit);
    return hit;
  };
  this.createBoxHit = function(gfx, type, attrs) {
    attrs = index_esm.assign({
      x: 0,
      y: 0
    }, attrs);
    var hit = index_esm$2.create("rect");
    applyStyle(hit, type);
    index_esm$2.attr(hit, attrs);
    appendHit(gfx, hit);
    return hit;
  };
  this.updateDefaultHit = function(element, gfx) {
    var hit = index_esm$1.query(".djs-hit", gfx);
    if (!hit) {
      return;
    }
    if (element.waypoints) {
      RenderUtil.updateLine(hit, element.waypoints);
    } else {
      index_esm$2.attr(hit, {
        width: element.width,
        height: element.height
      });
    }
    return hit;
  };
  this.fire = fire;
  this.triggerMouseEvent = triggerMouseEvent;
  this.mouseHandler = mouseHandler;
  this.registerEvent = registerEvent;
  this.unregisterEvent = unregisterEvent;
}
InteractionEvents.$inject = [
  "eventBus",
  "elementRegistry",
  "styles"
];
exports.default = InteractionEvents;
