/* COPYRIGHT Esri - https://js.arcgis.com/1.2/LICENSE.txt */
import { c as customElement } from "../../chunks/runtime.js";
import { css, html } from "lit";
import { u as useT9n } from "../../chunks/useT9n.js";
import { LitElement } from "@arcgis/lumina";
import { createRef, ref } from "lit-html/directives/ref.js";
import * as go from "gojs";
import { g as getIconUrl } from "../../chunks/getItemIcon.js";
import { injectGlobal } from "@emotion/css";
import "../solution-item-accordion/customElement.js";
const styles = css`/** @license
 * Copyright 2025 Esri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#filter-bar {
  background-color: #f4f4f4;
  position: absolute;
  top: 16px;
  right: 220px;
  z-index: 100;
}

#filteredViewButtonDiv {
  padding: 16px 16px 4px 16px;
}

#graph-navigation-bar {
  background-color: #f4f4f4;
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 100;
}

#graph-navigation-controls {
  position: absolute;
  top: 0;
  right: 0;
}

.z-index-1 {
  z-index: 1;
}

#diagram-panel {
  --calcite-panel-space: 0px;
}

#diagram-shell-panel {
  --calcite-color-background: var(--calcite-color-foreground-1);
  padding: 16px;
}
`;
const cColumnSpacing = 15;
const cLayerSpacing = 15;
const cDiagramPadding = 10;
const cNodeSize = new go.Size(220, 48);
const cNodeBorderStrokeWidth = 1;
const cNodeCornerRadius$1 = 8;
const cNodeIconPanelSize = new go.Size(48, 48);
const cNodeIconSize = new go.Size(16, 16);
const cNodeTextLineSize = new go.Size(153, 17);
const cNodeTextFormat = '400 0.75rem "Avenir Next", Avenir, "Helvetica Neue", sans-serif';
const cNodeTextFormatBold = '700 0.75rem "Avenir Next", Avenir, "Helvetica Neue", sans-serif';
const cDiagramBackgroundColor = "#f4f4f4";
const cNodeBorderColor = "#cacaca";
const cNodeBackgroundColor = "#ffffff";
const cNodeTextColor = "#4a4a4a";
const cLinkColor = "#6a6a6a";
const cTooltipBackgroundColor = "#ffffff";
const cNormalNodeOpacity = 1;
const cDimmedNodeOpacity = 0.3;
const cNormalLinkOpacity = 1;
const cDimmedLinkOpacity = 0.2;
const cHighlightedLinkOpacity = 1;
function defineDiagram(graphicContainer) {
  const diagramDiv = document.createElement("div");
  diagramDiv.style.width = "100%";
  diagramDiv.style.height = "100%";
  graphicContainer.appendChild(diagramDiv);
  const diagram = new go.Diagram(
    diagramDiv,
    // create a Diagram for the HTML Div element
    {
      click: dispatchDiagramClickEvent,
      // handle diagram clicks
      contentAlignment: go.Spot.Center,
      // align document to the center of the viewport
      dragSelectingTool: null,
      // disable drag selection
      hoverDelay: 50,
      // milliseconds before mouse-hover displays information
      initialAutoScale: go.AutoScale.Uniform,
      // automatic zoom-to-fit
      layout: new go.LayeredDigraphLayout({
        columnSpacing: cColumnSpacing,
        layerSpacing: cLayerSpacing
      }),
      padding: cDiagramPadding,
      scrollMode: go.ScrollMode.Infinite,
      // allow infinite scrolling--beyond document bounds
      "toolManager.hoverDelay": 50,
      // 50 milliseconds before tooltip appears
      "toolManager.mouseWheelBehavior": go.WheelMode.Zoom
      // mouse wheel zooms instead of scrolls vertically
    }
  );
  diagram.nodeTemplate = new go.Node("Auto", {
    click: dispatchNodeClickEvent,
    movable: false,
    opacity: cNormalNodeOpacity,
    toolTip: new go.Adornment("Auto", {
      isShadowed: true,
      margin: new go.Margin(12, 16, 6, 16),
      // top, right, bottom, left
      padding: 0,
      shadowBlur: 16,
      shadowColor: "rgba(0, 0, 0, 0.16)",
      shadowOffset: new go.Point(0, 0)
    }).add(new go.Panel("Vertical", { background: cTooltipBackgroundColor, margin: 0 }).add(new go.TextBlock({ margin: 14 }).bind("text", "title")))
  }).bind("text", "title").add(
    new go.Shape({
      desiredSize: cNodeSize,
      fill: cNodeBackgroundColor,
      geometryString: createRoundedRectangleGeometryPath(
        cNodeSize.width,
        cNodeSize.height,
        cNodeCornerRadius$1,
        cNodeIconPanelSize.width,
        true
      ),
      height: cNodeSize.height,
      portId: "",
      stroke: cNodeBorderColor,
      strokeWidth: cNodeBorderStrokeWidth,
      width: cNodeSize.width
    })
  ).add(
    // Node content
    new go.Panel("Horizontal", {
      alignment: go.Spot.Left,
      stretch: go.Stretch.Horizontal
    }).add(
      // Icon panel
      new go.Panel("Horizontal", {
        alignment: go.Spot.Left,
        desiredSize: cNodeIconPanelSize,
        margin: 1
      }).add(
        new go.Panel("Horizontal", {
          alignment: go.Spot.Center,
          margin: 16
        }).add(
          new go.Picture({
            desiredSize: cNodeIconSize
          }).bind("source", "", (node) => getIconUrl(node.itemType, node.itemTypeKeywords))
        )
      ),
      // Label
      new go.Panel("Horizontal", {
        alignment: go.Spot.Right,
        margin: new go.Margin(4, 8, 0, 8)
        // top, right, bottom, left
      }).add(
        new go.Panel("Vertical", {}).add(
          // First line
          new go.TextBlock({
            alignment: go.Spot.Left,
            desiredSize: cNodeTextLineSize,
            font: cNodeTextFormatBold,
            overflow: go.TextOverflow.Ellipsis,
            stroke: cNodeTextColor,
            wrap: go.Wrap.None
          }).bind("text", "title"),
          // Second line
          new go.TextBlock({
            alignment: go.Spot.Left,
            desiredSize: cNodeTextLineSize,
            font: cNodeTextFormat,
            overflow: go.TextOverflow.Ellipsis,
            stroke: cNodeTextColor,
            wrap: go.Wrap.None
          }).bind("text", "itemTypeForDisplay")
        )
      )
    )
  );
  diagram.commandHandler.zoomFactor = 1.05;
  diagram.setDivBackground(cDiagramBackgroundColor);
  const selectingTool = diagram.toolManager.clickSelectingTool;
  selectingTool.standardMouseSelect = function() {
  };
  const draggingTool = diagram.toolManager.draggingTool;
  draggingTool.isEnabled = false;
  diagram.linkTemplate = new go.Link({
    corner: 5,
    movable: false,
    routing: go.Routing.Orthogonal,
    selectable: false
  }).add(
    new go.Shape({
      // the link path shape
      opacity: cNormalLinkOpacity,
      stroke: cLinkColor
    }),
    new go.Shape({
      // the 'to' arrowhead
      fill: cLinkColor,
      opacity: cNormalLinkOpacity,
      stroke: null,
      toArrow: "Standard"
    })
  );
  return diagram;
}
function drawDiagram(diagram, nodesAndLinks) {
  diagram.model = new go.GraphLinksModel(nodesAndLinks.nodes, nodesAndLinks.links, {
    linkFromPortIdProperty: "fromPort",
    linkToPortIdProperty: "toPort"
  });
}
function drawAndConnectControlBars(graphicContainer, diagram, translations, includeFilteredViewButton = true) {
  if (includeFilteredViewButton) {
    const filterViewButton = drawfilteredViewBar(graphicContainer, translations);
    filterViewButton.addEventListener(
      "calciteSwitchChange",
      () => document.dispatchEvent(new CustomEvent("filteredViewChanged", { detail: filterViewButton.checked }))
    );
  }
  const { resetButton, centerButton, zoomInButton, zoomOutButton } = drawNavigationBar(graphicContainer, translations);
  resetButton.addEventListener("click", () => reset(diagram));
  centerButton.addEventListener("click", () => diagram.zoomToFit());
  zoomInButton.addEventListener("click", () => diagram.commandHandler.increaseZoom());
  zoomOutButton.addEventListener("click", () => diagram.commandHandler.decreaseZoom());
}
function drawSolutionGraph(graphicContainer, nodesAndLinks, translations) {
  setStyles();
  const diagram = defineDiagram(graphicContainer);
  drawDiagram(diagram, nodesAndLinks);
  drawAndConnectControlBars(graphicContainer, diagram, translations);
  return diagram;
}
function getConnectedNodesAndLinks(diagramNode) {
  const connectedNodes = /* @__PURE__ */ new Set();
  const connectedLinks = /* @__PURE__ */ new Set();
  function traceFromLinks(node) {
    node.findLinksInto().each(
      (link) => {
        connectedLinks.add(link);
        const fromNode = link.fromNode;
        if (fromNode && !connectedNodes.has(fromNode)) {
          connectedNodes.add(fromNode);
          traceFromLinks(fromNode);
        }
      }
    );
  }
  traceFromLinks(diagramNode);
  function traceToLinks(node) {
    node.findLinksOutOf().each(
      (link) => {
        connectedLinks.add(link);
        const toNode = link.toNode;
        if (toNode && !connectedNodes.has(toNode)) {
          connectedNodes.add(toNode);
          traceToLinks(toNode);
        }
      }
    );
  }
  traceToLinks(diagramNode);
  return { connectedNodes, connectedLinks };
}
function getNodesAndLinks(collection, canClickToOpen = false, clickToOpenBaseUrl) {
  const groupPseudoNodes = [];
  const nodes = collection.map((template) => {
    if (template.type !== "Group") {
      const templateTag = createGraphTag(template);
      return createGraphNode(template, templateTag, canClickToOpen, clickToOpenBaseUrl);
    } else {
      groupPseudoNodes.push(template.id);
      return void 0;
    }
  }).filter((node) => node !== void 0);
  const links = [];
  nodes.forEach((node) => {
    const template = collection.find((entry) => entry.id === node.itemId);
    (template?.dependencies || []).forEach((dependencyId) => {
      const dependency = nodes.find((entry) => entry?.itemId === dependencyId);
      if (dependency) {
        links.push({
          from: dependency.key,
          fromSpot: go.Spot.AllSides,
          to: node.key,
          toSpot: go.Spot.AllSides
        });
      }
    });
  });
  return { nodes, links, groupPseudoNodes };
}
function highlightNode(focusNode, focus, highlightBorder, dimUnrelatedNodes = true) {
  const myDiagram = focusNode.diagram;
  if (!myDiagram) {
    return;
  }
  const animationSet = {};
  if (dimUnrelatedNodes) {
    for (const node of myDiagram.nodes) {
      animationSet[node.key] = node === focusNode ? cNormalNodeOpacity : cDimmedNodeOpacity;
    }
    for (const link of myDiagram.links) {
      const key = `${link.fromNode?.key}-${link.toNode?.key}`;
      animationSet[key] = cDimmedLinkOpacity;
    }
    {
      const { connectedNodes, connectedLinks } = getConnectedNodesAndLinks(focusNode);
      for (const node of connectedNodes) {
        animationSet[node.key] = cNormalNodeOpacity;
      }
      for (const link of connectedLinks) {
        const key = `${link.fromNode?.key}-${link.toNode?.key}`;
        animationSet[key] = cHighlightedLinkOpacity;
      }
    }
  }
  if (highlightBorder) {
    highlightBorder.adornedObject = focusNode;
  }
  if (dimUnrelatedNodes) {
    const animation = new go.Animation();
    animation.duration = 1;
    for (const node of myDiagram.nodes) {
      animation.add(node, "opacity", node.opacity, animationSet[node.key]);
    }
    for (const link of myDiagram.links) {
      const key = `${link.fromNode?.key}-${link.toNode?.key}`;
      animation.add(link, "opacity", link.opacity, animationSet[key]);
    }
    animation.start();
  }
}
function highlightNodes(nodeIds, nodes, focus, highlightBorders, dimUnrelatedNodes = true) {
  if (nodeIds.length === 0) {
    return;
  }
  const myDiagram = nodes[0].diagram;
  if (!myDiagram) {
    return;
  }
  const animationSet = {};
  if (dimUnrelatedNodes) {
    for (const node of myDiagram.nodes) {
      const isFocusNode = nodeIds.includes(node.key);
      animationSet[node.key] = !focus || isFocusNode ? cNormalNodeOpacity : cDimmedNodeOpacity;
    }
    for (const link of myDiagram.links) {
      const key = `${link.fromNode?.key}-${link.toNode?.key}`;
      animationSet[key] = focus ? cDimmedLinkOpacity : cNormalLinkOpacity;
    }
  }
  Object.keys(highlightBorders).forEach((key) => {
    highlightBorders[key].adornedObject = null;
  });
  if (dimUnrelatedNodes) {
    const animation = new go.Animation();
    animation.duration = 1;
    for (const node of myDiagram.nodes) {
      animation.add(node, "opacity", node.opacity, animationSet[node.key]);
    }
    for (const link of myDiagram.links) {
      const key = `${link.fromNode?.key}-${link.toNode?.key}`;
      animation.add(link, "opacity", link.opacity, animationSet[key]);
    }
    animation.start();
  }
}
function createGraphNode(template, templateTag, canClickToOpen = false, clickToOpenBaseUrl) {
  return {
    key: templateTag,
    title: template.title,
    itemId: template.id,
    itemType: template.type,
    itemTypeForDisplay: getTypeForDisplay(template.type, template.typeKeywords),
    itemTypeKeywords: template.typeKeywords,
    group: template.type,
    url: canClickToOpen ? `${clickToOpenBaseUrl}?id=${template.id}` : void 0
  };
}
function createGraphTag(template) {
  return template.id;
}
function createRoundedRectangleGeometryPath(width, height, radius, iconPanelWidth = 0, isFilled = false) {
  let path = "";
  if (isFilled) {
    path += "F";
  }
  const horizontalStraightLineLen = width - 2 * radius;
  const verticalStraightLineLen = height - 2 * radius;
  path += ` M${0} ${0}`;
  path += ` h${horizontalStraightLineLen}`;
  path += ` a${radius} ${radius} 0 0 1 ${radius} ${radius}`;
  path += ` v${verticalStraightLineLen}`;
  path += ` a${radius} ${radius} 0 0 1 ${-radius} ${radius}`;
  path += ` h${-horizontalStraightLineLen}`;
  path += ` a${radius} ${radius} 0 0 1 ${-radius} ${-radius}`;
  path += ` v${-verticalStraightLineLen}`;
  path += ` a${radius} ${radius} 0 0 1 ${radius} ${-radius}`;
  if (iconPanelWidth > 0) {
    path += ` M${iconPanelWidth - radius} ${0} v${height}`;
  }
  return path;
}
function dispatchDiagramClickEvent() {
  document.dispatchEvent(new CustomEvent("clickInDiagram"));
}
function dispatchNodeClickEvent(_evt, obj) {
  const node = obj.part;
  if (node instanceof go.Node) {
    node.selectionAdorned = false;
    document.dispatchEvent(new CustomEvent("clickOnNode", { detail: node }));
  }
}
function drawfilteredViewBar(graphicContainer, translations) {
  const filteredViewButton = document.createElement("calcite-switch");
  filteredViewButton.id = "filteredViewButton";
  filteredViewButton.label = translations.filteredView;
  const filteredViewButtonLabel = document.createElement("calcite-label");
  filteredViewButtonLabel.id = "filteredViewButtonLabel";
  filteredViewButtonLabel.setAttribute("layout", "inline");
  filteredViewButtonLabel.innerHTML = translations.filteredView;
  filteredViewButtonLabel.appendChild(filteredViewButton);
  const filteredViewButtonDiv = document.createElement("div");
  filteredViewButtonDiv.id = "filteredViewButtonDiv";
  filteredViewButtonDiv.appendChild(filteredViewButtonLabel);
  const actionBar = document.createElement("calcite-action-bar");
  actionBar.id = "filter-bar-controls";
  actionBar.layout = "horizontal";
  actionBar.expandDisabled = true;
  actionBar.appendChild(filteredViewButtonDiv);
  const filterBar = document.createElement("div");
  filterBar.id = "filter-bar";
  graphicContainer.appendChild(filterBar);
  filterBar.appendChild(actionBar);
  return filteredViewButton;
}
function drawNavigationBar(graphicContainer, translations) {
  const resetButton = document.createElement("calcite-action");
  resetButton.appearance = "solid";
  resetButton.icon = "reset";
  resetButton.id = "showHideGrayedOutButton";
  const resetButtonTooltip = document.createElement("calcite-tooltip");
  resetButtonTooltip.id = "resetButtonTooltip";
  resetButtonTooltip.innerHTML = translations.reset;
  resetButtonTooltip.overlayPositioning = "fixed";
  resetButtonTooltip.placement = "bottom";
  resetButtonTooltip.referenceElement = resetButton.id;
  const centerButton = document.createElement("calcite-action");
  centerButton.appearance = "solid";
  centerButton.icon = "zoom-to-object";
  centerButton.id = "centerButton";
  const centerButtonTooltip = document.createElement("calcite-tooltip");
  centerButtonTooltip.id = "centerButtonTooltip";
  centerButtonTooltip.innerHTML = translations.centerDiagram;
  centerButtonTooltip.overlayPositioning = "fixed";
  centerButtonTooltip.placement = "bottom";
  centerButtonTooltip.referenceElement = centerButton.id;
  const zoomInButton = document.createElement("calcite-action");
  zoomInButton.appearance = "solid";
  zoomInButton.icon = "plus";
  zoomInButton.id = "zoomInButton";
  const zoomInButtonTooltip = document.createElement("calcite-tooltip");
  zoomInButtonTooltip.id = "zoomInButtonTooltip";
  zoomInButtonTooltip.innerHTML = translations.zoomIn;
  zoomInButtonTooltip.overlayPositioning = "fixed";
  zoomInButtonTooltip.placement = "bottom";
  zoomInButtonTooltip.referenceElement = zoomInButton.id;
  const zoomOutButton = document.createElement("calcite-action");
  zoomOutButton.appearance = "solid";
  zoomOutButton.icon = "minus";
  zoomOutButton.id = "zoomOutButton";
  const zoomOutButtonTooltip = document.createElement("calcite-tooltip");
  zoomOutButtonTooltip.id = "zoomOutButtonTooltip";
  zoomOutButtonTooltip.innerHTML = translations.zoomOut;
  zoomOutButtonTooltip.overlayPositioning = "fixed";
  zoomOutButtonTooltip.placement = "bottom";
  zoomOutButtonTooltip.referenceElement = zoomOutButton.id;
  const actionBar = document.createElement("calcite-action-bar");
  actionBar.id = "graph-navigation-controls";
  actionBar.layout = "horizontal";
  actionBar.expandDisabled = true;
  actionBar.appendChild(resetButton);
  actionBar.appendChild(resetButtonTooltip);
  actionBar.appendChild(centerButton);
  actionBar.appendChild(centerButtonTooltip);
  actionBar.appendChild(zoomInButton);
  actionBar.appendChild(zoomInButtonTooltip);
  actionBar.appendChild(zoomOutButton);
  actionBar.appendChild(zoomOutButtonTooltip);
  const graphNavigationBar = document.createElement("div");
  graphNavigationBar.id = "graph-navigation-bar";
  graphicContainer.appendChild(graphNavigationBar);
  graphNavigationBar.appendChild(actionBar);
  return { resetButton, centerButton, zoomInButton, zoomOutButton };
}
function getTypeForDisplay(type, typeKeywords) {
  let _type = type;
  if (type === "Feature Service") {
    const isView = typeKeywords.indexOf("View Service") > -1;
    const isTable = typeKeywords.indexOf("Table") > -1;
    _type = isView && isTable ? "Table (hosted, view)" : isTable ? "Table (hosted)" : isView ? "Feature Layer (hosted, view)" : "Feature Layer (hosted)";
  }
  if (type === "Web Mapping Application") {
    _type = typeKeywords.indexOf("configurableApp") > -1 ? "Instant App" : _type;
  }
  _type = type === "Geoprocessing Service" ? "Tool" : _type;
  _type = type === "Feed" ? "Feed (hosted)" : _type;
  _type = type === "Real Time Analytic" ? "Real Time Analytic (hosted)" : _type;
  _type = type === "Big Data Analytic" ? "Big Data Analytic (hosted)" : _type;
  _type = type === "Vector Tile Service" ? "Tile Layer" : _type;
  return _type;
}
function reset(diagram) {
  diagram.zoomToFit();
  document.dispatchEvent(new CustomEvent("reset"));
}
function setStyles() {
  injectGlobal`
    #filter-bar {
      background-color: #f4f4f4;
      position: absolute;
      top: 16px;
      right: 220px;
      z-index: 100;
    }
    #filteredViewButtonDiv {
      padding: 16px 16px 4px 16px;
    }
    #graph-navigation-bar {
      background-color: #f4f4f4;
      position: absolute;
      top: 16px;
      right: 16px;
      z-index: 100;
    }
    #graph-navigation-controls {
      position: absolute;
      top: 0;
      right: 0;
    }
  `;
}
const cNodeCornerRadius = 8;
const cNodeCornerRadiusCornerSelectionBitmap = 1 | 2 | 4 | 8;
const cNodeHighlightColor = "#1e90ff";
const cNodeHighlightStrokeWidth = 4;
class SolutionDisplay {
  /**
   * Creates a new instance of the SolutionDisplay class.
   * @param indexPanel The Calcite panel element to use as the index panel.
   * @param diagramPanel The Calcite panel element to use as the diagram panel.
   * @param diagramTranslations Translation strings for the diagram.
   * @param diagramKey The license to use for the diagram.
   * @example &lt;caption>Expected environment&lt;/caption>
   *   &lt;calcite-shell>
   *     &lt;calcite-shell-panel id='indexPanel' slot='panel-start' width-scale='m'/>
   *     &lt;calcite-panel id='diagramPanel' style='display:flex;'/>
   *   &lt;/calcite-shell>
   */
  constructor(indexPanel, diagramPanel, diagramTranslations, diagramKey) {
    this.indexPanel = indexPanel;
    this.diagramPanel = diagramPanel;
    this.diagramTranslations = diagramTranslations;
    this.diagramKey = diagramKey;
    this.currentSelectedGroupId = "";
    this.currentSelectedItemId = "";
    this.diagramNeedsRedraw = false;
    this.usefilteredView = false;
    this.handle_clickInDiagram = (evt) => {
      evt.stopImmediatePropagation();
      if (this.currentSelectedGroupId || this.currentSelectedItemId) {
        this.currentSelectedGroupId = "";
        this.currentSelectedItemId = "";
        this.diagramNeedsRedraw = this.usefilteredView;
        this.redraw();
      }
    };
    this.handle_clickOnNode = (evt) => {
      evt.stopImmediatePropagation();
      const id = evt.detail.data.key;
      this.redraw(id, id === this.currentSelectedItemId);
    };
    this.handle_filteredViewChanged = (evt) => {
      this.usefilteredView = evt.detail;
      this.diagramNeedsRedraw = !!this.currentSelectedGroupId || !!this.currentSelectedItemId;
      this.redraw(this.currentSelectedItemId || this.currentSelectedGroupId);
    };
    this.handle_reset = (evt) => {
      evt.stopImmediatePropagation();
      this.reset();
    };
    this.handle_solutionItemSelect = (evt) => {
      evt.stopImmediatePropagation();
      const id = evt.detail.itemId;
      this.redraw(id, id === this.currentSelectedItemId || id === this.currentSelectedGroupId, false);
    };
    if (go.Diagram.licenseKey === "") {
      go.Diagram.licenseKey = diagramKey ?? "";
    }
  }
  /**
   * Creates the index and diagram for the given collection of template info.
   * @param collection The collection of template info to display.
   * @param typeKeywords The collection type keywords for the solution.
   * @returns A promise that resolves when the index and diagram have been created.
   */
  create(collection, typeKeywords) {
    this.collection = collection;
    this.index = document.createElement("solution-item-accordion");
    this.index.linkType = "action";
    this.index.listSelectionMode = "single";
    this.index.typeKeywords = typeKeywords;
    this.index.style.overflowY = "auto";
    this.indexPanel.appendChild(this.index);
    this.index.templateInfos = collection;
    this.allNodesAndLinks = getNodesAndLinks(collection);
    this.diagram = drawSolutionGraph(
      this.diagramPanel,
      this.allNodesAndLinks,
      this.diagramTranslations
    );
    this.diagram.addDiagramListener("LayoutCompleted", () => {
      setTimeout(() => {
        this.diagram.zoomToFit();
      }, 1e3);
    });
    go.Link.setRoutingParameter(44, 600942);
    this.createNodeHighlighters();
    document.addEventListener("clickInDiagram", this.handle_clickInDiagram);
    document.addEventListener("clickOnNode", this.handle_clickOnNode);
    document.addEventListener("filteredViewChanged", this.handle_filteredViewChanged);
    document.addEventListener("reset", this.handle_reset);
    this.index.addEventListener("solutionItemSelect", this.handle_solutionItemSelect);
  }
  /**
   * Destroys the index and diagram; removes all event listeners.
   */
  dispose() {
    document.removeEventListener("clickInDiagram", this.handle_clickInDiagram);
    document.removeEventListener("clickOnNode", this.handle_clickOnNode);
    document.removeEventListener("filteredViewChanged", this.handle_filteredViewChanged);
    document.removeEventListener("reset", this.handle_reset);
    this.index.removeEventListener("solutionItemSelect", this.handle_solutionItemSelect);
    this.indexPanel.innerHTML = "";
    this.diagramPanel.innerHTML = "";
  }
  // ---------------------------------------------------------------------------------------------------------------- //
  /**
   * Clears all selections in the index and diagram.
   * @param alsoCollapseAllAccordionItems Whether to collapse all accordion items in the index
   */
  clearSelections(alsoCollapseAllAccordionItems = true) {
    void this.index.deselectAll();
    if (alsoCollapseAllAccordionItems) {
      void this.index.collapseAll();
    }
    const nodes = this.getNodesFromDiagram(this.diagram);
    const nodeIds = nodes.map((node) => node.data.key);
    highlightNodes(nodeIds, nodes, false, this.diagramNodeHighlighterIndex);
  }
  /**
   * Creates indicies into the diagram's nodes and node highlighters.
   * Rebuilds this.diagramNodeIndex and this.diagramNodeHighlighterIndex.
   */
  createNodeHighlighters() {
    this.diagramNodeIndex = {};
    this.diagramNodeHighlighterIndex = {};
    const nodes = this.getNodesFromDiagram(this.diagram);
    nodes.forEach((node) => {
      this.diagramNodeIndex[node.data.key] = node;
      const nodeHighlighter = new go.Adornment("Auto", {
        background: "transparent",
        margin: 2
      });
      nodeHighlighter.add(new go.Shape("RoundedRectangle", {
        fill: "transparent",
        parameter1: cNodeCornerRadius,
        parameter2: cNodeCornerRadiusCornerSelectionBitmap,
        stroke: cNodeHighlightColor,
        strokeWidth: cNodeHighlightStrokeWidth
      }));
      nodeHighlighter.add(new go.Placeholder({
        margin: 1
      }));
      this.diagramNodeHighlighterIndex[node.data.key] = nodeHighlighter;
    });
  }
  /**
   * Retrieves a node from the diagram by its id.
   * @param diagram The diagram to search
   * @param id Id of node to find
   * @returns Node matching the given id, or undefined if not found
   */
  getNodeById(id) {
    return this.diagramNodeIndex[id];
  }
  /**
   * Retrieves all nodes from the diagram.
   * @param diagram The diagram to search
   * @returns Array of nodes in the diagram
   */
  getNodesFromDiagram(diagram) {
    const nodes = [];
    const nodeIterator = diagram.nodes.iterator;
    while (nodeIterator.next()) {
      nodes.push(nodeIterator.value);
    }
    return nodes;
  }
  /**
   * Selects an item to highlight or unhighlight.
   * @param id Id of selected item
   * @param toggleSelection Whether to toggle the selection state of the item
   * @param alsoCollapseAllAccordionItems Whether to collapse all accordion items in the index
   */
  redraw(id = "", toggleSelection = false, alsoCollapseAllAccordionItems = true) {
    const areDrawingAGroup = this.allNodesAndLinks.groupPseudoNodes.includes(id);
    if (this.diagramNeedsRedraw) {
      drawDiagram(this.diagram, this.allNodesAndLinks);
      this.createNodeHighlighters();
      this.diagramNeedsRedraw = false;
    }
    let needsReset = false;
    this.clearSelections(alsoCollapseAllAccordionItems);
    if (!id) {
      return;
    }
    if (areDrawingAGroup) {
      this.currentSelectedItemId = "";
      if (this.currentSelectedGroupId !== id) {
        this.currentSelectedGroupId = id;
      } else if (toggleSelection) {
        this.currentSelectedGroupId = this.currentSelectedGroupId ? "" : id;
        needsReset = this.usefilteredView && !this.currentSelectedGroupId;
      }
      if (this.currentSelectedGroupId) {
        if (this.usefilteredView) {
          drawDiagram(this.diagram, this.allNodesAndLinks);
          this.createNodeHighlighters();
        }
        const group = this.collection.filter((item) => item.id === id)[0];
        const groupNodes = group.dependencies.map((dependency) => this.diagramNodeIndex[dependency]);
        if (this.usefilteredView) {
          const nodes = groupNodes.map((node) => node.data);
          drawDiagram(this.diagram, { nodes, links: [] });
        } else {
          highlightNodes(group.dependencies, groupNodes, true, this.diagramNodeHighlighterIndex);
        }
        void this.index.selectItem(this.currentSelectedGroupId);
      }
    } else {
      this.currentSelectedGroupId = "";
      if (this.currentSelectedItemId !== id) {
        this.currentSelectedItemId = id;
      } else if (toggleSelection) {
        this.currentSelectedItemId = this.currentSelectedItemId ? "" : id;
        needsReset = this.usefilteredView && !this.currentSelectedItemId;
      }
      let focusNode = this.getNodeById(id);
      if (!focusNode || this.usefilteredView) {
        drawDiagram(this.diagram, this.allNodesAndLinks);
        this.createNodeHighlighters();
        focusNode = this.getNodeById(id);
        if (!focusNode) {
          return;
        }
      }
      if (this.currentSelectedItemId) {
        if (this.usefilteredView) {
          const connectedNodesAndLinks = getConnectedNodesAndLinks(focusNode);
          connectedNodesAndLinks.connectedNodes.add(focusNode);
          const nodes = Array.from(connectedNodesAndLinks.connectedNodes).map((node) => node.data);
          const links = Array.from(connectedNodesAndLinks.connectedLinks).map((link) => link.data);
          drawDiagram(this.diagram, { nodes, links });
          this.createNodeHighlighters();
          focusNode = this.getNodeById(id);
          if (!focusNode) {
            return;
          }
        }
        if (focusNode) {
          setTimeout(() => highlightNode(focusNode, true, this.diagramNodeHighlighterIndex[id]), 1);
        }
        void this.index.selectItem(this.currentSelectedItemId);
      }
    }
    if (needsReset) {
      this.reset();
    }
  }
  /**
   * Clears all selections in the index and diagram.
   */
  reset() {
    this.diagramNeedsRedraw = false;
    this.currentSelectedGroupId = "";
    this.currentSelectedItemId = "";
    drawDiagram(this.diagram, this.allNodesAndLinks);
    this.createNodeHighlighters();
    this.clearSelections();
  }
}
class SolutionItemDiagram extends LitElement {
  constructor() {
    super(...arguments);
    this.diagramKey = "";
    this.templateInfoGraph = [];
    this.typeKeywords = [];
    this._diagramPanel = createRef();
    this._diagramShell = createRef();
    this._translations = useT9n({ name: "solution-item-diagram", blocking: true });
  }
  static {
    this.properties = { diagramKey: 1, templateInfoGraph: [0, {}, { attribute: false }], typeKeywords: [0, {}, { attribute: false }], _diagramPanel: [16, {}, { state: true }], _diagramShell: [16, {}, { state: true }], _translations: [16, {}, { state: true }] };
  }
  static {
    this.styles = styles;
  }
  updated() {
    if (this.solutionDisplay) {
      this.solutionDisplay.dispose();
      this.solutionDisplay = void 0;
    }
    if (this.templateInfoGraph.length > 0) {
      const graphsTranslations = {
        centerDiagram: this._translations.graphTranslations.centerDiagram,
        filteredView: this._translations.graphTranslations.filteredView,
        reset: this._translations.graphTranslations.reset,
        zoomIn: this._translations.graphTranslations.zoomIn,
        zoomOut: this._translations.graphTranslations.zoomOut
      };
      this.solutionDisplay = new SolutionDisplay(this._diagramShell.value, this._diagramPanel.value, graphsTranslations, this.diagramKey);
      this.solutionDisplay.create(this.templateInfoGraph, this.typeKeywords);
    }
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    if (this.solutionDisplay) {
      this.solutionDisplay.dispose();
      this.solutionDisplay = void 0;
    }
  }
  render() {
    return html`<calcite-shell><calcite-shell-panel id=diagram-shell-panel slot=panel-start ${ref(this._diagramShell)}></calcite-shell-panel><calcite-panel class="z-index-1" id=diagram-panel slot=panel-bottom ${ref(this._diagramPanel)}></calcite-panel></calcite-shell>`;
  }
}
customElement("solution-item-diagram", SolutionItemDiagram);
export {
  SolutionItemDiagram
};
