function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
/*
 * Copyright OpenSearch Contributors
 * SPDX-License-Identifier: Apache-2.0
 */
import React from 'react';
import { useEdgesState, useNodesState } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import { useEffect, useState } from 'react';
import { useMapInitialization } from './shared/hooks/use_map_initialization.hook';
import { useCelestialStateContext } from './shared/contexts/celestial_state_context';
import './celestial.scss';
import { useBreadcrumbs } from './components/breadcrumb_trail';
import { MapContainer } from './components/map_container';
import { CelestialNodeActionsProvider } from './shared/contexts/node_actions_context';
import { useCelestialLayout } from './shared/hooks/use_celestial_layout.hook';
import { useCelestialMapActions } from './shared/hooks/use_celestial_map_actions.hook';
import { useFitViewWithDelay } from './shared/hooks/use_fit_view_with_delay.hook';
import { useFocusOnNodes } from './shared/hooks/use_focus_on_nodes.hook';
import { jsx as _jsx } from "react/jsx-runtime";
/**
 * Detect whether the host page is in dark mode by reading the computed
 * color-scheme on :root. OSD sets :root { color-scheme: dark|light } at
 * bootstrap time based on the user's theme preference.
 */
const useIsDarkMode = () => {
  const _useState = useState(() => {
      if (typeof window === 'undefined') return false;
      return getComputedStyle(document.documentElement).colorScheme === 'dark';
    }),
    _useState2 = _slicedToArray(_useState, 2),
    isDark = _useState2[0],
    setIsDark = _useState2[1];
  useEffect(() => {
    const observer = new MutationObserver(() => {
      setIsDark(getComputedStyle(document.documentElement).colorScheme === 'dark');
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['style']
    });
    return () => observer.disconnect();
  }, []);

  // Sync dark mode class to document.documentElement so CSS rules can reach
  // portal-rendered content (e.g. LegendPanel) that lives outside .celestial.
  useEffect(() => {
    const root = document.documentElement;
    if (isDark) {
      root.classList.add('celestial--dark');
    } else {
      root.classList.remove('celestial--dark');
    }
    return () => root.classList.remove('celestial--dark');
  }, [isDark]);
  return isDark;
};
export const Celestial = props => {
  var _props$map, _props$map2, _props$breadcrumbs, _props$addBreadcrumb, _props$navigateToBrea;
  const isDarkMode = useIsDarkMode();
  const fitViewWithDelay = useFitViewWithDelay();
  const _useFocusOnNodes = useFocusOnNodes(),
    focusOnNodes = _useFocusOnNodes.focusOnNodes;
  const _useCelestialStateCon = useCelestialStateContext(),
    viewLock = _useCelestialStateCon.viewLock;

  // Pass the layout options from props to the hook
  const _useCelestialLayout = useCelestialLayout(props.layoutOptions),
    getLaidOutElements = _useCelestialLayout.getLaidOutElements;

  // Replace the current static initialization with a reactive approach
  const _useNodesState = useNodesState([]),
    _useNodesState2 = _slicedToArray(_useNodesState, 3),
    nodes = _useNodesState2[0],
    setNodes = _useNodesState2[1],
    onNodesChange = _useNodesState2[2];
  const _useEdgesState = useEdgesState([]),
    _useEdgesState2 = _slicedToArray(_useEdgesState, 3),
    edges = _useEdgesState2[0],
    setEdges = _useEdgesState2[1],
    onEdgesChange = _useEdgesState2[2];
  const _useCelestialStateCon2 = useCelestialStateContext(),
    setSelectedNodeId = _useCelestialStateCon2.setSelectedNodeId;

  // Stack aggregated nodes and focus other nodes
  const map = useMapInitialization((_props$map = props.map) === null || _props$map === void 0 || (_props$map = _props$map.root) === null || _props$map === void 0 ? void 0 : _props$map.nodes, (_props$map2 = props.map) === null || _props$map2 === void 0 || (_props$map2 = _props$map2.root) === null || _props$map2 === void 0 ? void 0 : _props$map2.edges, props.nodesInFocus, props.topN);
  useEffect(() => {
    const layoutResult = getLaidOutElements(map.nodes, map.edges);

    // Update the ReactFlow states
    setNodes(layoutResult.nodes);
    setEdges(layoutResult.edges);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [map.nodes, map.edges, getLaidOutElements]);

  // focus on selected nodeid
  useEffect(() => {
    setSelectedNodeId(props.selectedNodeId);
    if (props.selectedNodeId) {
      const selectedNode = nodes.find(node => node.id === props.selectedNodeId);
      if (selectedNode && !selectedNode.hidden) {
        focusOnNodes([selectedNode], nodes);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [props.selectedNodeId, nodes, focusOnNodes]);
  useEffect(() => {
    if (map.nodes) {
      var _map$edges, _props$nodesInFocus;
      const layoutResult = getLaidOutElements(map.nodes, (_map$edges = map.edges) !== null && _map$edges !== void 0 ? _map$edges : []);
      setNodes(layoutResult.nodes);
      setEdges(layoutResult.edges);
      if ((_props$nodesInFocus = props.nodesInFocus) !== null && _props$nodesInFocus !== void 0 && _props$nodesInFocus.length) {
        focusOnNodes(props.nodesInFocus, layoutResult.nodes);
      } else if (!viewLock.isLocked()) {
        fitViewWithDelay();
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [map.nodes, map.edges, focusOnNodes, fitViewWithDelay, props.nodesInFocus]);

  // Use breadcrumb props if provided, otherwise fall back to internal hook for backwards compatibility
  const internalBreadcrumbs = useBreadcrumbs();
  const breadcrumbs = (_props$breadcrumbs = props.breadcrumbs) !== null && _props$breadcrumbs !== void 0 ? _props$breadcrumbs : internalBreadcrumbs.breadcrumbs;
  const addBreadcrumb = (_props$addBreadcrumb = props.addBreadcrumb) !== null && _props$addBreadcrumb !== void 0 ? _props$addBreadcrumb : internalBreadcrumbs.addBreadcrumb;
  const navigateToBreadcrumb = (_props$navigateToBrea = props.navigateToBreadcrumb) !== null && _props$navigateToBrea !== void 0 ? _props$navigateToBrea : internalBreadcrumbs.navigateToBreadcrumb;
  const _useCelestialMapActio = useCelestialMapActions({
      onDataFetch: props.onDataFetch,
      navigateToBreadcrumb,
      onEdgeClick: props.onEdgeClick,
      onBreadcrumbClick: props.onBreadcrumbClick
    }),
    onBreadcrumbClick = _useCelestialMapActio.onBreadcrumbClick,
    onEdgeClick = _useCelestialMapActio.onEdgeClick;
  return /*#__PURE__*/_jsx(CelestialNodeActionsProvider, {
    onDataFetch: props.onDataFetch,
    addBreadcrumb: addBreadcrumb,
    onDashboardClick: props.onDashboardClick,
    children: /*#__PURE__*/_jsx("div", {
      className: "celContainer celestial reset".concat(isDarkMode ? ' celestial--dark' : ''),
      children: /*#__PURE__*/_jsx("div", {
        className: "celMapContainer",
        children: /*#__PURE__*/_jsx(MapContainer, {
          isDarkMode: isDarkMode,
          isLoading: props.isLoading,
          nodes: nodes,
          edges: edges,
          onNodesChange: onNodesChange,
          onEdgesChange: onEdgesChange,
          breadcrumbs: breadcrumbs,
          onBreadcrumbClick: onBreadcrumbClick,
          onEdgeClick: onEdgeClick,
          emptyState: props.emptyState,
          hotspot: props.breadcrumbHotspot,
          numMatches: props.numMatchesForFilters,
          nodeTypes: props.nodeTypes,
          edgeTypes: props.edgeTypes,
          legend: props.legend,
          showMinimap: props.showMinimap,
          showSliSlo: props.showSliSlo,
          showLayoutControls: props.showLayoutControls,
          nodesDraggable: props.nodesDraggable,
          rootBreadcrumbIcon: props.rootBreadcrumbIcon,
          onNodeClickZoom: props.onNodeClickZoom,
          onEdgeClickZoom: props.onEdgeClickZoom
        })
      })
    })
  });
};