import {
  MasterDetailTable,
  PanelContainer,
  Searchbar,
  Select
} from "./chunk-34BKYKWL.mjs";

// src/panels/mesh/SignalPanel/SignalPanel.tsx
import React3 from "react";

// src/panels/mesh/SignalPanel/SignalMessageTable.tsx
import React, { useEffect, useMemo, useState } from "react";
import { Format } from "@dxos/echo/internal";
import { ConnectionState } from "@dxos/protocols/proto/dxos/client/services";
import { PublicKey, useClient } from "@dxos/react-client";
import { useDevtools } from "@dxos/react-client/devtools";
import { useNetworkStatus } from "@dxos/react-client/mesh";
import { Toolbar } from "@dxos/react-ui";
var views = [
  {
    id: "swarm-event",
    title: "SwarmEvent",
    filter: (response) => {
      return !!response.swarmEvent;
    },
    // TODO(burdon): Fixed width for date.
    // TODO(burdon): Add id property (can't use date?) Same for swarm panel.
    properties: [
      {
        name: "receivedAt",
        format: Format.TypeFormat.DateTime,
        title: "received",
        sort: "desc",
        size: 194
      },
      {
        name: "response",
        format: Format.TypeFormat.SingleSelect,
        size: 100,
        config: {
          options: [
            {
              id: "Available",
              title: "Available",
              color: "green"
            },
            {
              id: "Left",
              title: "Left",
              color: "neutral"
            }
          ]
        }
      },
      {
        name: "peer",
        format: Format.TypeFormat.DID
      },
      {
        name: "since",
        format: Format.TypeFormat.DateTime,
        size: 194
      },
      {
        name: "topic",
        format: Format.TypeFormat.DID
      }
    ],
    dataTransform: (response) => ({
      id: `${response.receivedAt?.getTime()}-${Math.random()}`,
      receivedAt: response.receivedAt,
      response: response.swarmEvent?.peerAvailable ? "Available" : response.swarmEvent?.peerLeft ? "Left" : void 0,
      peer: response.swarmEvent.peerAvailable && PublicKey.from(response.swarmEvent.peerAvailable.peer).toString() || response.swarmEvent.peerLeft && PublicKey.from(response.swarmEvent.peerLeft.peer).toString(),
      since: response.swarmEvent.peerAvailable?.since ?? /* @__PURE__ */ new Date(),
      topic: response.topic && PublicKey.from(response.topic).toString(),
      _original: response
    })
  },
  {
    id: "message",
    title: "Message",
    filter: (response) => {
      return !!response.message;
    },
    properties: [
      {
        name: "receivedAt",
        format: Format.TypeFormat.DateTime,
        title: "received",
        size: 194
      },
      {
        name: "author",
        format: Format.TypeFormat.DID
      },
      {
        name: "recipient",
        format: Format.TypeFormat.DID
      },
      {
        name: "message",
        format: Format.TypeFormat.DID
      },
      {
        name: "topic",
        format: Format.TypeFormat.DID
      }
    ],
    dataTransform: (response) => ({
      id: `${response.receivedAt?.getTime()}-${Math.random()}`,
      receivedAt: response.receivedAt,
      author: PublicKey.from(response.message.author).toString(),
      recipient: PublicKey.from(response.message.recipient).toString(),
      message: response.message.payload.messageId,
      topic: response.message.payload?.payload?.topic,
      _original: response
    })
  },
  {
    id: "ack",
    title: "Acknowledgement",
    filter: (response) => {
      return response.message?.payload["@type"] === "dxos.mesh.messaging.Acknowledgement";
    },
    properties: [
      {
        name: "receivedAt",
        format: Format.TypeFormat.DateTime,
        title: "received",
        size: 194
      },
      {
        name: "author",
        format: Format.TypeFormat.DID
      },
      {
        name: "recipient",
        format: Format.TypeFormat.DID
      },
      {
        name: "message",
        format: Format.TypeFormat.DID
      }
    ],
    dataTransform: (response) => ({
      id: `${response.receivedAt?.getTime()}-${Math.random()}`,
      receivedAt: response.receivedAt,
      author: PublicKey.from(response.message.author).toString(),
      recipient: PublicKey.from(response.message.recipient).toString(),
      message: response.message.payload.messageId,
      _original: response
    })
  }
];
var getView = (id) => views.find((type) => type.id === id);
var ToggleConnection = ({ connection, onToggleConnection }) => /* @__PURE__ */ React.createElement(Toolbar.IconButton, {
  icon: connection === ConnectionState.ONLINE ? "ph--wifi-high--regular" : "ph--wifi-slash--regular",
  iconOnly: true,
  size: 6,
  label: "Toggle connection",
  classNames: "mli-2 p-0 pli-2 items-center",
  onClick: onToggleConnection
});
var SignalMessageTable = () => {
  const devtoolsHost = useDevtools();
  const [messages, setMessages] = useState([]);
  useEffect(() => {
    const signalOutput = devtoolsHost.subscribeToSignal();
    const signalResponses = [];
    signalOutput.subscribe((response) => {
      signalResponses.push(response);
      setMessages([
        ...signalResponses
      ]);
    });
    return () => {
      void signalOutput.close();
    };
  }, []);
  const [viewType, setViewType] = useState("swarm-event");
  const [search, setSearch] = useState("");
  const view = viewType ? getView(viewType) : void 0;
  const filteredMessages = getFilteredData(messages, view, search);
  const client = useClient();
  const { swarm: connectionState } = useNetworkStatus();
  const handleToggleConnection = async () => {
    switch (connectionState) {
      case ConnectionState.OFFLINE: {
        await client.mesh.updateConfig(ConnectionState.ONLINE);
        break;
      }
      case ConnectionState.ONLINE: {
        await client.mesh.updateConfig(ConnectionState.OFFLINE);
        break;
      }
    }
  };
  const tableData = useMemo(() => {
    if (!view) {
      return [];
    }
    return filteredMessages.map(view.dataTransform);
  }, [
    filteredMessages,
    view
  ]);
  return /* @__PURE__ */ React.createElement("div", {
    className: "flex flex-col flex-1 overflow-hidden"
  }, /* @__PURE__ */ React.createElement(Toolbar.Root, null, /* @__PURE__ */ React.createElement(Select, {
    items: views.map(({ id, title }) => ({
      value: id,
      label: title
    })),
    value: viewType,
    onValueChange: (type) => setViewType(type)
  }), /* @__PURE__ */ React.createElement(Searchbar, {
    onChange: setSearch
  }), /* @__PURE__ */ React.createElement(ToggleConnection, {
    connection: connectionState,
    onToggleConnection: handleToggleConnection
  })), view && /* @__PURE__ */ React.createElement(MasterDetailTable, {
    properties: view.properties,
    data: tableData,
    detailsTransform: (d) => d._original
  }));
};
var getFilteredData = (messages, view, searchText) => {
  const defaultSubFilter = (match) => (object) => {
    if (!match) {
      return true;
    }
    return JSON.stringify(object).includes(match);
  };
  return view ? messages.filter(view.filter).filter(view.subFilter ? view.subFilter(searchText) : defaultSubFilter(searchText)) : messages;
};

// src/panels/mesh/SignalPanel/SignalStatusTable.tsx
import { formatDistance } from "date-fns";
import React2, { useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
import { scheduleTaskInterval } from "@dxos/async";
import { Context } from "@dxos/context";
import { Format as Format2 } from "@dxos/echo/internal";
import { SignalState } from "@dxos/protocols/proto/dxos/mesh/signal";
import { useDevtools as useDevtools2, useStream } from "@dxos/react-client/devtools";
import { DynamicTable } from "@dxos/react-ui-table";
var __dxlog_file = "/__w/dxos/dxos/packages/devtools/devtools/src/panels/mesh/SignalPanel/SignalStatusTable.tsx";
var getSignalStatus = (server) => {
  return {
    connectionStarted: server.connectionStarted,
    lastStateChange: server.lastStateChange,
    reconnectIn: server.reconnectIn,
    host: server.host,
    state: server.state
  };
};
var signalStateLabels = {
  [SignalState.CONNECTING]: "CONNECTING",
  [SignalState.RECONNECTING]: "RECONNECTING",
  [SignalState.CONNECTED]: "CONNECTED",
  [SignalState.DISCONNECTED]: "DISCONNECTED",
  [SignalState.ERROR]: "ERROR",
  [SignalState.CLOSED]: "CLOSED",
  UNKNOWN: "UNKNOWN"
};
var stateColors = {
  CONNECTING: "orange",
  RECONNECTING: "orange",
  CONNECTED: "green",
  DISCONNECTED: "orange",
  ERROR: "red",
  CLOSED: "neutral",
  UNKNOWN: "neutral"
};
var getStateLabel = (state) => {
  return signalStateLabels[state] ?? "UNKNOWN";
};
var tableProperties = [
  {
    name: "host",
    format: Format2.TypeFormat.String,
    size: 240
  },
  {
    name: "status",
    format: Format2.TypeFormat.SingleSelect,
    size: 140,
    config: {
      options: Object.values(signalStateLabels).map((label) => ({
        id: label,
        title: label,
        color: stateColors[label]
      }))
    }
  },
  {
    name: "connected",
    format: Format2.TypeFormat.String,
    size: 240
  }
];
var SignalStatusTable = () => {
  const devtoolsHost = useDevtools2();
  const { servers } = useStream(() => devtoolsHost.subscribeToSignalStatus(), {
    servers: []
  });
  const status = servers.map(getSignalStatus);
  const [time, setTime] = useState2(/* @__PURE__ */ new Date());
  useEffect2(() => {
    const ctx = new Context(void 0, {
      F: __dxlog_file,
      L: 87
    });
    scheduleTaskInterval(ctx, async () => {
      setTime(/* @__PURE__ */ new Date());
    }, 1e3);
    return () => {
      void ctx.dispose();
    };
  }, []);
  if (!servers) {
    return null;
  }
  const properties = useMemo2(() => tableProperties, []);
  const rows = useMemo2(() => {
    return status.map((status2, index) => ({
      id: `${index}-${status2.host}`,
      host: new URL(status2.host).origin,
      status: getStateLabel(status2.state),
      connected: status2.state === SignalState.CONNECTED ? formatDistance(status2.lastStateChange.getTime(), time.getTime(), {
        includeSeconds: true,
        addSuffix: true
      }) : `Reconnecting ${formatDistance(time.getTime(), status2.lastStateChange.getTime() + status2.reconnectIn, {
        addSuffix: true
      })}`,
      _original: status2
    }));
  }, [
    status,
    time
  ]);
  return /* @__PURE__ */ React2.createElement(DynamicTable, {
    properties,
    rows
  });
};

// src/panels/mesh/SignalPanel/SignalPanel.tsx
var SignalPanel = () => {
  return /* @__PURE__ */ React3.createElement(PanelContainer, {
    classNames: "grid grid-rows-[2fr_5fr]"
  }, /* @__PURE__ */ React3.createElement(SignalStatusTable, null), /* @__PURE__ */ React3.createElement(SignalMessageTable, null));
};

// src/panels/mesh/SignalPanel/index.ts
var SignalPanel_default = SignalPanel;
export {
  SignalPanel_default as default
};
//# sourceMappingURL=SignalPanel-V2OWTBI2.mjs.map
