import { reduce, forEach } from "../../../min-dash/dist/index.esm.mjs";
import { getChildren, getVisual } from "../util/GraphicsUtil.mjs";
import { translate } from "../util/SvgTransformUtil.mjs";
import { clear } from "../../../min-dom/dist/index.esm.mjs";
import { create, classes, append, attr, remove } from "../../../tiny-svg/dist/index.esm.mjs";
import { isFrameElement } from "../util/Elements.mjs";
function GraphicsFactory(eventBus, elementRegistry) {
  this._eventBus = eventBus;
  this._elementRegistry = elementRegistry;
}
GraphicsFactory.$inject = ["eventBus", "elementRegistry"];
GraphicsFactory.prototype._getChildrenContainer = function(element) {
  var gfx = this._elementRegistry.getGraphics(element);
  var childrenGfx;
  if (!element.parent) {
    childrenGfx = gfx;
  } else {
    childrenGfx = getChildren(gfx);
    if (!childrenGfx) {
      childrenGfx = create("g");
      classes(childrenGfx).add("djs-children");
      append(gfx.parentNode, childrenGfx);
    }
  }
  return childrenGfx;
};
GraphicsFactory.prototype._clear = function(gfx) {
  var visual = getVisual(gfx);
  clear(visual);
  return visual;
};
GraphicsFactory.prototype._createContainer = function(type, childrenGfx, parentIndex, isFrame) {
  var outerGfx = create("g");
  classes(outerGfx).add("djs-group");
  if (typeof parentIndex !== "undefined") {
    prependTo(outerGfx, childrenGfx, childrenGfx.childNodes[parentIndex]);
  } else {
    append(childrenGfx, outerGfx);
  }
  var gfx = create("g");
  classes(gfx).add("djs-element");
  classes(gfx).add("djs-" + type);
  if (isFrame) {
    classes(gfx).add("djs-frame");
  }
  append(outerGfx, gfx);
  var visual = create("g");
  classes(visual).add("djs-visual");
  append(gfx, visual);
  return gfx;
};
GraphicsFactory.prototype.create = function(type, element, parentIndex) {
  var childrenGfx = this._getChildrenContainer(element.parent);
  return this._createContainer(type, childrenGfx, parentIndex, isFrameElement(element));
};
GraphicsFactory.prototype.updateContainments = function(elements) {
  var self = this, elementRegistry = this._elementRegistry, parents;
  parents = reduce(elements, function(map, e) {
    if (e.parent) {
      map[e.parent.id] = e.parent;
    }
    return map;
  }, {});
  forEach(parents, function(parent) {
    var children = parent.children;
    if (!children) {
      return;
    }
    var childrenGfx = self._getChildrenContainer(parent);
    forEach(children.slice().reverse(), function(child) {
      var childGfx = elementRegistry.getGraphics(child);
      prependTo(childGfx.parentNode, childrenGfx);
    });
  });
};
GraphicsFactory.prototype.drawShape = function(visual, element) {
  var eventBus = this._eventBus;
  return eventBus.fire("render.shape", { gfx: visual, element });
};
GraphicsFactory.prototype.getShapePath = function(element) {
  var eventBus = this._eventBus;
  return eventBus.fire("render.getShapePath", element);
};
GraphicsFactory.prototype.drawConnection = function(visual, element) {
  var eventBus = this._eventBus;
  return eventBus.fire("render.connection", { gfx: visual, element });
};
GraphicsFactory.prototype.getConnectionPath = function(waypoints) {
  var eventBus = this._eventBus;
  return eventBus.fire("render.getConnectionPath", waypoints);
};
GraphicsFactory.prototype.update = function(type, element, gfx) {
  if (!element.parent) {
    return;
  }
  var visual = this._clear(gfx);
  if (type === "shape") {
    this.drawShape(visual, element);
    translate(gfx, element.x, element.y);
  } else if (type === "connection") {
    this.drawConnection(visual, element);
  } else {
    throw new Error("unknown type: " + type);
  }
  if (element.hidden) {
    attr(gfx, "display", "none");
  } else {
    attr(gfx, "display", "block");
  }
};
GraphicsFactory.prototype.remove = function(element) {
  var gfx = this._elementRegistry.getGraphics(element);
  remove(gfx.parentNode);
};
function prependTo(newNode, parentNode, siblingNode) {
  var node = siblingNode || parentNode.firstChild;
  if (newNode === node) {
    return;
  }
  parentNode.insertBefore(newNode, node);
}
export {
  GraphicsFactory as default
};
