"use strict";
var import_UPlotChart = require("../../../UPlotChart.css");
const jsxRuntime = require("react/jsx-runtime");
const _ = require("lodash");
const React = require("react");
const throttleDebounce = require("throttle-debounce");
const uPlot = require("uplot");
const kit_Button = require("../../Button.cjs");
const kit_Icon = require("../../Icon.cjs");
const kit_internal_useResize = require("../useResize.cjs");
const kit_LineChart_SyncProvider = require("../../LineChart/SyncProvider.cjs");
const kit_Spinner = require("../../Spinner.cjs");
const kit_Theme_UI = require("../../Theme/UI.cjs");
require("../../Theme/themeUtils.cjs");
require("../../Theme/themes.cjs");
const kit_utils_error = require("../../utils/error.cjs");
const kit_utils_usePrevious = require("../../utils/usePrevious.cjs");
const base = "UPlotChart_base_43d12";
const dark = "UPlotChart_dark_43d12";
const chartEmpty = "UPlotChart_chartEmpty_43d12";
const download = "UPlotChart_download_43d12";
const invisibleLink = "UPlotChart_invisibleLink_43d12";
const css = {
  base,
  dark,
  chartEmpty,
  download,
  invisibleLink
};
const SCROLL_THROTTLE_TIME = 500;
const shouldRecreate = (prev, next) => {
  var _a, _b, _c, _d, _e, _f;
  if (!next)
    return false;
  if (!prev)
    return true;
  if (prev === next)
    return false;
  if (prev.key !== next.key)
    return true;
  if (Object.keys(prev).length !== Object.keys(next).length)
    return true;
  if (((_a = prev.axes) == null ? void 0 : _a.length) !== ((_b = next.axes) == null ? void 0 : _b.length))
    return true;
  if (!_.isEqual(prev.plugins, next.plugins))
    return true;
  if (((_c = prev == null ? void 0 : prev.series) == null ? void 0 : _c.length) !== ((_d = next.series) == null ? void 0 : _d.length))
    return true;
  const someScaleHasChanged = Object.entries(next.scales ?? {}).some(([scaleKey, nextScale]) => {
    var _a2;
    const prevScale = (_a2 = prev == null ? void 0 : prev.scales) == null ? void 0 : _a2[scaleKey];
    return (prevScale == null ? void 0 : prevScale.distr) !== (nextScale == null ? void 0 : nextScale.distr);
  });
  if (someScaleHasChanged)
    return true;
  const someAxisHasChanged = (_e = prev.axes) == null ? void 0 : _e.some((prevAxis, seriesIdx) => {
    var _a2;
    const nextAxis = (_a2 = next.axes) == null ? void 0 : _a2[seriesIdx];
    return prevAxis.label !== (nextAxis == null ? void 0 : nextAxis.label) || prevAxis.stroke !== (nextAxis == null ? void 0 : nextAxis.stroke) || prevAxis.scale !== (nextAxis == null ? void 0 : nextAxis.scale);
  });
  if (someAxisHasChanged)
    return true;
  const someSeriesHasChanged = (_f = prev.series) == null ? void 0 : _f.some((prevSerie, seriesIdx) => {
    var _a2, _b2, _c2;
    const nextSerie = (_a2 = next.series) == null ? void 0 : _a2[seriesIdx];
    return (nextSerie == null ? void 0 : nextSerie.label) != null && (prevSerie == null ? void 0 : prevSerie.label) !== (nextSerie == null ? void 0 : nextSerie.label) || (prevSerie == null ? void 0 : prevSerie.stroke) != null && (prevSerie == null ? void 0 : prevSerie.stroke) !== (nextSerie == null ? void 0 : nextSerie.stroke) || (nextSerie == null ? void 0 : nextSerie.paths) != null && (prevSerie == null ? void 0 : prevSerie.paths) !== (nextSerie == null ? void 0 : nextSerie.paths) || (nextSerie == null ? void 0 : nextSerie.fill) != null && (prevSerie == null ? void 0 : prevSerie.fill) !== (nextSerie == null ? void 0 : nextSerie.fill) || ((_b2 = prevSerie == null ? void 0 : prevSerie.points) == null ? void 0 : _b2.show) !== ((_c2 = nextSerie == null ? void 0 : nextSerie.points) == null ? void 0 : _c2.show);
  });
  if (someSeriesHasChanged)
    return true;
  return false;
};
const UPlotChart = ({
  allowDownload,
  data,
  isLoading,
  options,
  handleError,
  experimentId,
  xAxis
}) => {
  var _a;
  const chartRef = React.useRef();
  const { refObject, refCallback, size } = kit_internal_useResize();
  const classes = [css.base];
  const {
    themeSettings: { themeIsDark, theme }
  } = kit_Theme_UI.useTheme();
  const { options: syncOptions, syncService } = kit_LineChart_SyncProvider.useChartSync();
  const chartType = (options == null ? void 0 : options.mode) === 2 ? "Scatter" : "Line";
  const hasData = data && data.length > 1 && (chartType === "Scatter" || ((_a = data == null ? void 0 : data[0]) == null ? void 0 : _a.length));
  if (themeIsDark)
    classes.push(css.dark);
  React.useEffect(() => {
    if (data !== void 0 && chartType === "Line")
      syncService.updateDataBounds(data, xAxis);
  }, [syncService, chartType, data, xAxis]);
  const extendedOptions = React.useMemo(() => {
    var _a2;
    const extended = uPlot.assign(
      {
        width: size.width
      },
      chartType === "Line" ? syncOptions : {},
      options ?? {}
    );
    if (chartType === "Line") {
      const activeBounds = syncService.activeBounds.get();
      if (activeBounds) {
        const { min, max } = activeBounds;
        const xScale = (_a2 = extended.scales) == null ? void 0 : _a2.x;
        if (xScale) {
          xScale.max = max;
          xScale.min = min;
        }
      }
    }
    if (theme && extended.axes) {
      const borderColor = theme.surfaceBorderWeak;
      const labelColor = theme.surfaceOn;
      extended.axes = extended.axes.map((axis) => {
        return {
          ...axis,
          border: { stroke: borderColor },
          grid: { ...axis.grid, stroke: borderColor },
          stroke: labelColor,
          ticks: { ...axis.ticks, stroke: borderColor }
        };
      });
    }
    return extended;
  }, [options, theme, chartType, size.width, syncOptions, syncService]);
  const previousOptions = kit_utils_usePrevious(extendedOptions, void 0);
  React.useEffect(() => {
    return () => {
      var _a2;
      (_a2 = chartRef == null ? void 0 : chartRef.current) == null ? void 0 : _a2.destroy();
      chartRef.current = void 0;
    };
  }, []);
  React.useEffect(() => {
    var _a2, _b, _c, _d, _e;
    if (!refObject.current)
      return;
    if (!hasData) {
      (_a2 = chartRef.current) == null ? void 0 : _a2.destroy();
      chartRef.current = void 0;
      return;
    }
    if (!chartRef.current || shouldRecreate(previousOptions, extendedOptions)) {
      (_b = chartRef.current) == null ? void 0 : _b.destroy();
      chartRef.current = void 0;
      try {
        if (chartType === "Scatter" || extendedOptions.series.length === (data == null ? void 0 : data.length)) {
          chartRef.current = new uPlot(extendedOptions, data, refObject.current);
        }
      } catch (e) {
        (_c = chartRef.current) == null ? void 0 : _c.destroy();
        chartRef.current = void 0;
        handleError == null ? void 0 : handleError(e, {
          level: kit_utils_error.ErrorLevel.Error,
          publicMessage: "Unable to Load data for chart",
          publicSubject: "Bad Data",
          silent: false,
          type: kit_utils_error.ErrorType.Ui
        });
      }
    } else {
      try {
        (_d = chartRef.current) == null ? void 0 : _d.setData(data, chartType === "Scatter");
      } catch (e) {
        (_e = chartRef.current) == null ? void 0 : _e.destroy();
        chartRef.current = void 0;
        handleError == null ? void 0 : handleError(e, {
          level: kit_utils_error.ErrorLevel.Error,
          publicMessage: "Unable to Load data for chart",
          publicSubject: "Bad Data",
          silent: false,
          type: kit_utils_error.ErrorType.Ui
        });
      }
    }
  }, [data, hasData, extendedOptions, previousOptions, refObject, handleError, chartType]);
  React.useEffect(() => {
    extendedOptions.series.forEach((ser, i) => {
      var _a2, _b, _c;
      const chartSer = (_b = (_a2 = chartRef.current) == null ? void 0 : _a2.series) == null ? void 0 : _b[i];
      if (chartSer && chartSer.show !== (ser == null ? void 0 : ser.show))
        (_c = chartRef.current) == null ? void 0 : _c.setSeries(i, { show: ser.show }, false);
    });
  }, [extendedOptions.series]);
  React.useEffect(() => {
    if (!chartRef.current)
      return;
    const [width, height] = [size.width, (options == null ? void 0 : options.height) || chartRef.current.height];
    if (chartRef.current.width === width && chartRef.current.height === height)
      return;
    chartRef.current.setSize({ height, width });
  }, [options == null ? void 0 : options.height, refObject, size]);
  React.useEffect(() => {
    const throttleFunc = throttleDebounce.throttle(SCROLL_THROTTLE_TIME, () => {
      if (chartRef.current)
        chartRef.current.syncRect();
    });
    const handleScroll = () => throttleFunc();
    document.addEventListener("scroll", handleScroll, true);
    return () => {
      document.removeEventListener("scroll", handleScroll);
      throttleFunc.cancel();
    };
  }, []);
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.join(" "), ref: refCallback, style: { minHeight: 250 }, children: [
    allowDownload && /* @__PURE__ */ jsxRuntime.jsx(DownloadButton, { containerRef: refObject, experimentId }),
    !hasData && !isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: css.chartEmpty, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: "No data to plot." }) }),
    isLoading && /* @__PURE__ */ jsxRuntime.jsx(kit_Spinner, { spinning: true, tip: "Loading chart data..." })
  ] });
};
const DownloadButton = ({
  containerRef,
  experimentId
}) => {
  const downloadUrl = React.useRef();
  const downloadNode = React.useRef(null);
  const fileName = React.useMemo(
    () => experimentId ? `chart-trial-${experimentId}.png` : "chart.png",
    [experimentId]
  );
  React.useEffect(() => {
    return () => {
      if (downloadUrl.current)
        URL.revokeObjectURL(downloadUrl.current);
    };
  }, []);
  const handleDownloadClick = React.useCallback(() => {
    var _a;
    if (downloadUrl.current)
      URL.revokeObjectURL(downloadUrl.current);
    const canvas = (_a = containerRef.current) == null ? void 0 : _a.querySelector("canvas");
    const url = canvas == null ? void 0 : canvas.toDataURL("image/png");
    if (url && downloadNode.current) {
      downloadNode.current.href = url;
      downloadNode.current.click();
    }
    downloadUrl.current = url;
  }, [containerRef]);
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx("div", { className: css.download, children: /* @__PURE__ */ jsxRuntime.jsx(
      kit_Button,
      {
        icon: /* @__PURE__ */ jsxRuntime.jsx(kit_Icon.default, { name: "download", showTooltip: true, size: "small", title: "Download Chart" }),
        type: "text",
        onClick: handleDownloadClick
      }
    ) }),
    /* @__PURE__ */ jsxRuntime.jsx(
      "a",
      {
        "aria-disabled": true,
        className: css.invisibleLink,
        download: fileName,
        href: downloadUrl.current,
        ref: downloadNode
      }
    )
  ] });
};
module.exports = UPlotChart;
