/* Copyright © 2020 Splunk Inc.
SPLUNK CONFIDENTIAL – Use or disclosure of this material in whole or
in part without a valid written license from Splunk Inc. is PROHIBITED. */
import {
  uPlot_min_exports,
  uplot_react_default,
  uplot_react_exports
} from "./chunk-FUNDGA5O.js";
import {
  def
} from "./chunk-SIXD2HQM.js";
import {
  getVizThemeForKey,
  themes_exports
} from "./chunk-P6Y5CKTH.js";
import {
  styled_components_default,
  styled_components_exports
} from "./chunk-5LUILIR3.js";
import {
  buildColorFunction,
  filterSplit,
  pixelStrToNum,
  roundToPoT,
  timeTickFormatter,
  uplot_default,
  uplot_exports
} from "./chunk-6N4JNZ5S.js";
import {
  lodash_exports
} from "./chunk-FWZM3EJJ.js";
import {
  react_default,
  react_exports
} from "./chunk-V3S5WUKN.js";
import {
  __export,
  __objRest,
  __reExport,
  __spreadValues
} from "./chunk-XC4WXK3L.js";

// esm-externals:@splunk/ui-utils/format
var format_exports = {};
__export(format_exports, {
  default: () => format_default
});
__reExport(format_exports, format_star);
import * as defaultImport from "@splunk/ui-utils/format";
import * as format_star from "@splunk/ui-utils/format";
var format_default = "default" in defaultImport ? defaultImport.default : defaultImport;

// src/Heatmap.styled.tsx
var StyledHeatMap = styled_components_default.div`
    ${({ gap, theme }) => `
        gap: ${gap}px;
        --tooltip-line-stroke: ${theme.tooltip.lineStroke};
    `}
    align-items: center;
    display: flex;

    /* Overwrite uplot style */
    .uplot {
        position: relative;
    }

    .u-select {
        background: rgba(0, 0, 0, 0.3);
    }

    .u-hz .u-cursor-x {
        border-right: 1px solid var(--tooltip-line-stroke);
    }
`;

// src/Heatmap.tsx
var DEFAULT_LEGEND_HEIGHT = 300;
var DEFAULT_LEGEND_WIDTH = 25;
var LEGEND_WIDTH = 100;
var CHART_GAP = 20;
var HeatmapLegend = ({ yMaxValue, width, height, yLegendLabel, data, theme }) => {
  const buildPathsForLegend = (legendWidth) => (u, seriesIdx) => {
    uplot_default.orient(
      u,
      seriesIdx,
      (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => {
        const resolutionScale = window.devicePixelRatio || 1;
        const legendValuePosition = (legendWidth + 5) * resolutionScale;
        const scaledLegendWidth = legendWidth * resolutionScale;
        const textSize = theme.heatmap.axisFontSize * resolutionScale;
        u.ctx.font = `${textSize}px Arial`;
        const colors = theme.heatmap.colorScheme;
        const numColors = colors.length;
        const bucketPixelHeight = Math.round(yDim / numColors);
        let bucketColorIdx = 0;
        u.ctx.fillStyle = theme.heatmap.axisStroke;
        u.ctx.fillText("0", legendValuePosition, yOff + yDim);
        u.ctx.fillText(
          (0, format_exports.abbreviateNumber)(yMaxValue >= 10 ? Math.round(yMaxValue) : yMaxValue),
          legendValuePosition,
          yOff
        );
        for (let i = 0; i < yDim; i += 1) {
          u.ctx.fillStyle = colors[bucketColorIdx];
          u.ctx.fillRect(0, yOff + yDim - i, scaledLegendWidth, 1);
          if (i !== 0 && i % bucketPixelHeight === 0) {
            bucketColorIdx += 1;
            const bucketValue = yMaxValue / numColors * bucketColorIdx;
            u.ctx.fillStyle = theme.heatmap.axisStroke;
            u.ctx.fillText(
              // only use decimals when values < 10 so that axis label does not get cut off
              (0, format_exports.abbreviateNumber)(bucketValue >= 10 ? Math.round(bucketValue) : bucketValue),
              legendValuePosition,
              yOff + yDim - i
            );
          }
        }
      }
    );
    return null;
  };
  const normalizedHeight = height <= 0 ? DEFAULT_LEGEND_HEIGHT : height;
  const normalizedWidth = width <= 0 ? DEFAULT_LEGEND_WIDTH : width;
  const options = {
    width: LEGEND_WIDTH,
    height: normalizedHeight,
    mode: 2,
    cursor: { show: false },
    legend: { show: false },
    axes: [
      {
        // invisible axis here to match canvas positioning of heatmap path
        size: 75,
        grid: { show: false },
        ticks: { show: false }
      },
      {
        show: true,
        size: 45,
        label: yLegendLabel,
        labelFont: "bold 12px Arial",
        side: 1,
        grid: { show: false },
        ticks: { show: false },
        values: [null],
        stroke: theme.heatmap.axisStroke
      }
    ],
    scales: {
      x: { min: 0, max: normalizedWidth, time: false },
      y: {
        min: 0,
        max: yMaxValue
      }
    },
    series: [{}, { paths: buildPathsForLegend(DEFAULT_LEGEND_WIDTH) }]
  };
  return /* @__PURE__ */ react_default.createElement(uplot_react_default, { options, data: [Array(data.length), data] });
};
function paths(timeInterval, sendLegendRangeMax, theme, sendAnalytics) {
  return (u, seriesIdx) => {
    uplot_default.orient(
      u,
      seriesIdx,
      (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => {
        try {
          const [startTimes, yStarts, yEnds, counts] = u.data[seriesIdx];
          const dlen = startTimes.length;
          const startTimePixelMap = {};
          let globalMaxCountPerSecond = 0;
          for (let i = 0; i < dlen; i += 1) {
            const startTime = startTimes[i];
            const yStart = yStarts[i];
            const yEnd = yEnds[i];
            const count = counts[i];
            const yDimInteger = Math.round(yDim);
            if (!startTimePixelMap[startTime]) {
              startTimePixelMap[startTime] = new Array(yDimInteger).fill(0);
            }
            const yTopPixelPos = Math.floor(valToPosY(yEnd, scaleY, yDim, 0));
            const yBottomPixelPos = Math.ceil(valToPosY(yStart, scaleY, yDim, 0));
            const heightPixels = Math.max(1, yBottomPixelPos - yTopPixelPos);
            const countPerSecond = count / heightPixels / timeInterval;
            for (let j = yTopPixelPos; j <= yTopPixelPos + heightPixels; j += 1) {
              startTimePixelMap[startTime][j] += countPerSecond;
              const val = startTimePixelMap[startTime][j];
              if (val) {
                globalMaxCountPerSecond = Math.max(globalMaxCountPerSecond, val);
              }
            }
          }
          const colorFn = buildColorFunction(globalMaxCountPerSecond, theme);
          u.ctx.fillStyle = theme.heatmap.colorScheme[0];
          u.ctx.fillRect(xOff, yOff, xDim, yDim);
          const uniqueStartTimes = Object.keys(startTimePixelMap);
          for (let i = 0; i < uniqueStartTimes.length; i += 1) {
            const rectangleStartTime = uniqueStartTimes[i];
            const rectanglePixelCountPerSecond = startTimePixelMap[rectangleStartTime];
            const numberStartTime = Number(rectangleStartTime);
            for (let j = 0; j < rectanglePixelCountPerSecond.length; j += 1) {
              const x = valToPosX(numberStartTime, scaleX, xDim, xOff);
              const width = valToPosX(numberStartTime + timeInterval, scaleX, xDim, xOff) - valToPosX(numberStartTime, scaleX, xDim, xOff);
              const canvasY = j + yOff;
              u.ctx.fillStyle = colorFn(rectanglePixelCountPerSecond[j]);
              u.ctx.fillRect(x, canvasY, width, 1);
            }
          }
          sendAnalytics == null ? void 0 : sendAnalytics("Data_View/Heatmap_Analyzer", "View_Load", null, "RenderSuccess");
          sendLegendRangeMax(globalMaxCountPerSecond);
        } catch (e) {
          sendAnalytics == null ? void 0 : sendAnalytics("Data_View/Heatmap_Analyzer", "View_Load", yDim, "RenderError");
        }
      }
    );
    return null;
  };
}
var InternalHeatmap = ({
  width,
  height,
  timeZone,
  userAnalytics,
  data,
  timeRangeEpochSeconds = { start: Infinity, end: 0 },
  yLegendLabel,
  yLabel,
  overlay
}) => {
  const { colorScheme } = (0, themes_exports.useSplunkTheme)();
  const theme = getVizThemeForKey(colorScheme);
  const [legendRangeMax, setLegendRange] = (0, react_exports.useState)();
  const [overlayParams, setOverlayParams] = (0, react_exports.useState)(null);
  let xMin;
  let xMax;
  let yMinRounded;
  let yMaxRounded;
  let xIntervalSeconds;
  const xs = data[0];
  const secondXValue = xs.find((x) => x !== xs[0]);
  if (secondXValue) {
    xMin = (timeRangeEpochSeconds == null ? void 0 : timeRangeEpochSeconds.start) || xs[0];
    xIntervalSeconds = secondXValue - xs[0];
    xMax = (timeRangeEpochSeconds == null ? void 0 : timeRangeEpochSeconds.end) || (0, lodash_exports.last)(xs) + xIntervalSeconds;
    const allYValues = [...data[1], ...data[2]];
    const yMin = (0, lodash_exports.min)(allYValues);
    yMinRounded = roundToPoT(yMin, Math.floor);
    const yMax = (0, lodash_exports.max)(allYValues);
    const yMaxNearestPoT = roundToPoT(yMax, Math.floor);
    yMaxRounded = Math.ceil(yMax / yMaxNearestPoT) * yMaxNearestPoT;
  } else if (timeRangeEpochSeconds) {
    xMin = timeRangeEpochSeconds.start;
    xMax = timeRangeEpochSeconds.end;
    yMinRounded = 1e6;
    yMaxRounded = 1e8;
    xIntervalSeconds = 1;
    data = [[], [], [], []];
  } else {
    throw new Error("Heatmap requires two or more points on the x axis, or a timeRangeEpochSeconds prop");
  }
  const heatmapWidth = width - (LEGEND_WIDTH + CHART_GAP);
  const options = {
    hooks: {
      setSize: [
        (u) => {
          if (def(u.over)) {
            const uOverStyles = u.over.style;
            const tempRenderProp = {
              uOverRect: {
                left: pixelStrToNum(uOverStyles.left),
                top: pixelStrToNum(uOverStyles.top),
                height: pixelStrToNum(uOverStyles.height),
                width: pixelStrToNum(uOverStyles.width)
              },
              posToVal: u.posToVal,
              valToPos: u.valToPos
            };
            if (!(0, lodash_exports.isEqual)(tempRenderProp.uOverRect, overlayParams == null ? void 0 : overlayParams.uOverRect)) {
              setOverlayParams(tempRenderProp);
            }
          }
        }
      ]
    },
    width: heatmapWidth,
    height,
    mode: 2,
    tzDate: (ts) => uplot_default.tzDate(new Date(ts * 1e3), timeZone),
    scales: {
      x: {
        time: true,
        min: xMin,
        max: xMax
      },
      y: {
        min: yMinRounded,
        max: yMaxRounded,
        distr: 3,
        auto: false
      }
    },
    series: [
      {},
      {
        paths: paths(xIntervalSeconds, setLegendRange, theme, userAnalytics == null ? void 0 : userAnalytics.event),
        stroke: theme.heatmap.axisStroke
      }
    ],
    cursor: {
      y: false,
      bind: {
        dblclick: () => null
      },
      drag: {
        setScale: false
      }
    },
    select: {
      show: false
    },
    axes: [
      {
        size: 75,
        grid: { show: false },
        ticks: { show: true, stroke: theme.heatmap.axisStroke, width: 1 },
        stroke: theme.heatmap.axisStroke
      },
      {
        show: true,
        size: 75,
        label: yLabel,
        labelGap: 5,
        labelSize: 30,
        filter: (u, splits) => {
          const splitsPos = splits.map((split) => u.valToPos(split, "y"));
          return splits.map((split, index) => filterSplit(index, split, splitsPos, u));
        },
        values: (u, splits) => splits.map((split) => split ? timeTickFormatter(split, "ns" /* Nanoseconds */) : ""),
        side: 3,
        grid: { show: false },
        ticks: { show: true, stroke: theme.heatmap.axisStroke, width: 1 },
        stroke: theme.heatmap.axisStroke
      }
    ],
    legend: {
      show: false
    }
  };
  return /* @__PURE__ */ react_default.createElement(react_default.Fragment, null, overlayParams ? overlay == null ? void 0 : overlay(overlayParams) : null, /* @__PURE__ */ react_default.createElement(StyledHeatMap, { "data-testid": "heatmap-root", gap: CHART_GAP, theme }, /* @__PURE__ */ react_default.createElement(
    uplot_react_default,
    {
      options,
      data: [Array(data.length), data]
    }
  ), legendRangeMax && /* @__PURE__ */ react_default.createElement("div", null, /* @__PURE__ */ react_default.createElement(
    HeatmapLegend,
    {
      yMaxValue: legendRangeMax,
      data,
      width: LEGEND_WIDTH,
      height,
      yLegendLabel,
      theme
    }
  ))));
};
var Heatmap = (_a) => {
  var _b = _a, { theme } = _b, props = __objRest(_b, ["theme"]);
  if (!theme) {
    return /* @__PURE__ */ react_default.createElement(InternalHeatmap, __spreadValues({}, props));
  }
  return /* @__PURE__ */ react_default.createElement(themes_exports.SplunkThemeProvider, { colorScheme: theme }, /* @__PURE__ */ react_default.createElement(InternalHeatmap, __spreadValues({}, props)));
};

export {
  Heatmap
};
//# sourceMappingURL=chunk-MI6TOBKM.js.map
