var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  return value;
};
import { jsx } from "react/jsx-runtime";
import { observable } from "micro-observables";
import { createContext, useMemo, useContext } from "react";
import uPlot from "uplot";
import { generateUUID } from "../internal/functions.js";
class SyncService {
  constructor(syncKey, xRange) {
    __publicField(this, "axis");
    __publicField(this, "bounds", observable({ dataBounds: null, unzoomedBounds: null, zoomBounds: null }));
    __publicField(this, "pubSub");
    __publicField(this, "activeBounds", this.bounds.select((b) => (b == null ? void 0 : b.zoomBounds) ?? (b == null ? void 0 : b.unzoomedBounds)));
    __publicField(this, "key");
    __publicField(this, "xRange");
    this.key = syncKey ?? generateUUID();
    this.pubSub = uPlot.sync(this.key);
    this.xRange = xRange;
    this.activeBounds.subscribe((activeBounds) => {
      if (!activeBounds)
        return;
      const { min, max } = activeBounds;
      this.pubSub.plots.forEach((u) => {
        u.setScale("x", { max, min });
      });
    });
  }
  syncChart(chart) {
    const activeBounds = this == null ? void 0 : this.activeBounds.get();
    if (activeBounds)
      chart.setScale("x", activeBounds);
  }
  resetZoom() {
    this.bounds.update((b) => {
      var _a, _b, _c, _d, _e;
      let resetBounds = null;
      if (this.axis && ((_a = this.xRange) == null ? void 0 : _a[this.axis])) {
        resetBounds = {
          max: ((_c = (_b = this.xRange) == null ? void 0 : _b[this.axis]) == null ? void 0 : _c[1]) ?? 1,
          min: ((_e = (_d = this.xRange) == null ? void 0 : _d[this.axis]) == null ? void 0 : _e[0]) ?? 0
        };
      }
      return { ...b, zoomBounds: resetBounds };
    });
  }
  setZoom(min, max) {
    this.bounds.update((b) => ({ ...b, zoomBounds: { max, min } }));
  }
  updateDataBounds(data, axis) {
    const xValues = data[0];
    const lastIdx = xValues.length - 1;
    const chartMin = xValues[0];
    const chartMax = xValues[lastIdx];
    if (chartMin === void 0 || chartMax === void 0)
      return;
    this.bounds.update((b) => {
      var _a, _b, _c, _d, _e, _f;
      const resetAxis = axis !== this.axis && !!axis && !!this.axis;
      if (axis) {
        this.axis = axis;
      }
      const previousMin = ((_a = b.dataBounds) == null ? void 0 : _a.min) !== void 0 && isFinite((_b = b.dataBounds) == null ? void 0 : _b.min) && !resetAxis ? (_c = b.dataBounds) == null ? void 0 : _c.min : chartMin;
      const previousMax = ((_d = b.dataBounds) == null ? void 0 : _d.max) !== void 0 && isFinite((_e = b.dataBounds) == null ? void 0 : _e.max) && !resetAxis ? (_f = b.dataBounds) == null ? void 0 : _f.max : chartMax;
      const dataMin = Math.min(previousMin, chartMin);
      const dataMax = Math.max(previousMax, chartMax);
      const width = dataMax - dataMin;
      const margin = 0.02 * width;
      const unzoomedMin = width > 0 ? dataMin - margin : Math.min(dataMin, 0);
      let unzoomedMax = width > 0 ? dataMax + margin : 2 * dataMax;
      if (unzoomedMin === unzoomedMax) {
        unzoomedMax = 1;
      }
      return {
        ...b,
        dataBounds: { max: dataMax, min: dataMin },
        unzoomedBounds: { max: unzoomedMax, min: unzoomedMin },
        zoomBounds: resetAxis ? null : b.zoomBounds
      };
    });
  }
}
const SyncContext = createContext(null);
const SyncProvider = ({ syncKey, children, xRange }) => {
  const syncService = useMemo(() => new SyncService(syncKey, xRange), [syncKey, xRange]);
  return /* @__PURE__ */ jsx(SyncContext.Provider, { value: syncService, children });
};
const useChartSync = () => {
  const syncProviderService = useContext(SyncContext);
  const syncService = useMemo(
    () => syncProviderService ?? new SyncService(),
    [syncProviderService]
  );
  const options = useMemo(() => {
    const syncKey = syncService == null ? void 0 : syncService.pubSub.key;
    const syncScales = ["x", null];
    return {
      cursor: {
        bind: {
          dblclick: () => {
            return () => {
              syncService == null ? void 0 : syncService.resetZoom();
              return null;
            };
          }
        },
        drag: { dist: 5, setScale: false, uni: 10, x: true, y: false },
        sync: {
          key: syncKey,
          scales: syncScales,
          setSeries: false
        }
      },
      hooks: {
        init: [syncService.syncChart],
        ready: [syncService.syncChart],
        setData: [(chart) => syncService.updateDataBounds(chart.data)],
        setSelect: [
          (chart) => {
            const min = chart.posToVal(chart.select.left, "x");
            const max = chart.posToVal(chart.select.left + chart.select.width, "x");
            syncService == null ? void 0 : syncService.setZoom(min, max);
            chart.setSelect({ height: 0, left: 0, top: 0, width: 0 }, false);
          }
        ]
      }
    };
  }, [syncService]);
  return { options, syncService };
};
export {
  SyncProvider,
  useChartSync
};
