/* 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 {
  formatDurationMicros,
  formatTimestamp,
  lodash_exports,
  scaleTime,
  shortenByte,
  shortenNumber
} from "./chunk-FWZM3EJJ.js";
import {
  react_exports
} from "./chunk-V3S5WUKN.js";
import {
  __export,
  __pow,
  __reExport,
  __spreadProps,
  __spreadValues
} from "./chunk-XC4WXK3L.js";

// esm-externals:uplot
var uplot_exports = {};
__export(uplot_exports, {
  default: () => uplot_default
});
__reExport(uplot_exports, uplot_star);
import * as defaultImport from "uplot";
import * as uplot_star from "uplot";
var uplot_default = "default" in defaultImport ? defaultImport.default : defaultImport;

// esm-externals:lodash/some
var some_exports = {};
__export(some_exports, {
  default: () => some_default
});
__reExport(some_exports, some_star);
import * as defaultImport2 from "lodash/some";
import * as some_star from "lodash/some";
var some_default = "default" in defaultImport2 ? defaultImport2.default : defaultImport2;

// src/utilities/utils.ts
var SECOND_TO_MICROSECOND = 1e6;
var SECOND_TO_MILLISECOND = 1e3;
var DAY = 24 * 60 * 60;
function exists(value) {
  return value !== void 0 && value !== null;
}
function isNumber(num) {
  return exists(num) && Number.isFinite(num);
}
function useDynamicCallback(callback) {
  const ref = (0, react_exports.useRef)(callback);
  (0, react_exports.useLayoutEffect)(() => {
    ref.current = callback;
  }, [callback]);
  return (0, react_exports.useCallback)((...args) => {
    var _a;
    (_a = ref.current) == null ? void 0 : _a.call(ref, ...args);
  }, []);
}
function useCreateAttachedDivElement(attachTo, className) {
  const iElRef = (0, react_exports.useRef)(document.createElement("div"));
  (0, react_exports.useLayoutEffect)(() => {
    if (!className) {
      return;
    }
    iElRef.current.className = className;
    const el = attachTo == null ? void 0 : attachTo.querySelector(className);
    if (attachTo && !el) {
      attachTo.appendChild(iElRef.current);
    }
  }, [attachTo, className]);
  return iElRef.current;
}
function getMergedSeriesConfigForField(seriesConfigMap = {}, scaleConfigMap = {}, field) {
  const defaults = { scale: "y" };
  if (!exists(field)) {
    return defaults;
  }
  const seriesConfig = seriesConfigMap[field];
  const scale = (seriesConfig == null ? void 0 : seriesConfig.scale) || "y";
  const scaleConfig = scaleConfigMap[scale] || {};
  const mergedSeriesConfig = __spreadValues(__spreadValues(__spreadValues({}, defaults), scaleConfig.seriesConfig), seriesConfig);
  return mergedSeriesConfig;
}
function getMergedSeriesConfig(seriesConfigMap = {}, scaleConfigMap = {}) {
  return Object.keys(seriesConfigMap).reduce((acc, field) => {
    acc[field] = getMergedSeriesConfigForField(seriesConfigMap, scaleConfigMap, field);
    return acc;
  }, {});
}
var formatKibBytes = (bytes, decimals = 2) => {
  if (!+bytes) {
    return "0B";
  }
  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return `${parseFloat((bytes / __pow(k, i)).toFixed(dm))}${sizes[i]}`;
};
var valueFormatters = {
  durationMicros: (value) => value,
  rate: (value) => value,
  count: (value) => value,
  bytes: (value) => value,
  percentage: (value) => +value.toFixed(value < 10 ? 2 : 1),
  kibBytes: (value) => value
};
var namedFormatters = {
  durationMicros: (value) => formatDurationMicros(value),
  rate: (value, xAxisResolution) => `${shortenNumber(value / (xAxisResolution || 1))} /s`,
  count: (value) => `${shortenNumber(value)}`,
  bytes: (value) => `${shortenByte(value)}`,
  percentage: (value) => `${shortenNumber(value)}%`,
  kibBytes: (value) => `${formatKibBytes(value, 0)}`
};
var scaleNamedFormatters = __spreadProps(__spreadValues({}, namedFormatters), {
  percentage: (value) => `${shortenNumber(value, value < 10 ? 3 : 2)}%`
});
var getXAxisResolution = (data) => {
  if ((0, lodash_exports.isEmpty)(data.columns)) {
    return 0;
  }
  const timeSeries = data.columns[0];
  const firstNonNullIndex = timeSeries.findIndex((val, i) => val !== null && timeSeries[i + 1] !== null);
  if (firstNonNullIndex === -1) {
    return 0;
  }
  return timeSeries[firstNonNullIndex + 1] - timeSeries[firstNonNullIndex];
};
var formatValueWithSeriesConfig = (value, seriesConfig, data) => {
  const formatter = seriesConfig.valueFmt;
  if (!formatter) {
    return String(value);
  }
  const formatFn = typeof formatter === "string" ? namedFormatters[formatter] : formatter;
  const xAxisResolution = getXAxisResolution(data);
  return formatFn(value, xAxisResolution);
};
var formatValueForPlottingWithSeriesConfig = (value, seriesConfig, data) => {
  const formatter = seriesConfig.valueFmt;
  if (!formatter) {
    return value;
  }
  const formatFn = typeof formatter === "string" ? valueFormatters[formatter] : formatter;
  const xAxisResolution = isTimeSeriesData(data) ? getXAxisResolution(data) : null;
  return formatFn(value, xAxisResolution);
};
var formatValueWithScaleConfig = (value, scaleConfig, xAxisResolution) => {
  const formatter = scaleConfig.tickFmt;
  if (!formatter) {
    return String(value);
  }
  const formatFn = typeof formatter === "string" ? scaleNamedFormatters[formatter] : formatter;
  return formatFn(value, xAxisResolution);
};
var findClosest = (arr, target) => {
  let closest = null;
  if (target > arr[arr.length - 1] || target < arr[0]) {
    return closest;
  }
  const sortedIdx = (0, lodash_exports.sortedIndex)(arr, target);
  const leftVal = arr[sortedIdx - 1];
  const rightVal = arr[sortedIdx];
  const middle = Math.floor((leftVal + rightVal) / 2);
  if (target >= middle) {
    closest = rightVal;
  } else {
    closest = leftVal;
  }
  return closest;
};
var buildColorFunction = (maxDensity, theme) => (value) => {
  const colors = theme.heatmap.colorScheme;
  const bucketIndex = Math.round(value / maxDensity * (colors.length - 1));
  return colors[bucketIndex];
};
var timeTickFormatter = (tickValue, startingScale, decimalPlaces) => {
  const { value, scale } = scaleTime(tickValue, startingScale, decimalPlaces);
  return value + scale;
};
var filterSplit = (index, split, splitsPos, u) => {
  const mod = index % 9;
  if (mod === 0) {
    return split;
  }
  if (mod === 1) {
    const textMetrics = u.ctx.measureText(String(split));
    const textHeight = textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent;
    return textHeight + 1 <= Math.abs(splitsPos[index] - splitsPos[index - 1]) ? split : null;
  }
  return null;
};
var roundToPoT = (value, roundFunc) => __pow(10, roundFunc(Math.log10(value)));
var pixelStrToNum = (str) => Number(str.replace("px", ""));
var X_AXIS_TIME_OPTIONS = {
  None: 0,
  "1Min": 60,
  "1Hour": 3600,
  "2Hours": 7200,
  "6Hours": 21600,
  "12Hours": 43200,
  "1Day": 86400,
  "2Days": 172800,
  "8Days": 691200
};
var markPrefix = "mark-";
var buildSeriesForLegend = (series, reversedOrder, marks) => {
  const slicedSeries = series.slice(1);
  if (reversedOrder) {
    slicedSeries.reverse();
  }
  marks == null ? void 0 : marks.forEach(({ legendLabel, color }) => {
    if (!legendLabel) {
      return;
    }
    slicedSeries.push({
      field: `${markPrefix}${legendLabel}`,
      fill: color,
      label: legendLabel,
      show: true
    });
  });
  return slicedSeries;
};
var getTickInterval = (tickDiff) => {
  if (tickDiff < 6e4) {
    return "1s";
  }
  if (tickDiff < 36e5) {
    return "1m";
  }
  if (tickDiff < 18e6) {
    return "30m";
  }
  if (tickDiff < 432e5) {
    return "1h";
  }
  if (tickDiff < 864e5) {
    return "12h";
  }
  if (tickDiff < 6048e5) {
    return "1d";
  }
  if (tickDiff < 2592e6) {
    return "7d";
  }
  return "1mo";
};
var getDefaultExpandedFormatTimeStampLabelParts = (millisecondsEpoch, tickInterval, locale) => {
  const date = new Date(millisecondsEpoch);
  const time = tickInterval === "1s" ? date.toLocaleTimeString([], {
    timeZone: locale.tz,
    hour: "numeric",
    minute: "2-digit",
    second: "2-digit"
  }) : date.toLocaleTimeString([], {
    timeZone: locale.tz,
    hour: "numeric",
    minute: "2-digit"
  });
  const day = date.toLocaleDateString([], {
    timeZone: locale.tz,
    weekday: "short",
    month: "short",
    day: "numeric"
  });
  const month = date.toLocaleDateString([], {
    timeZone: locale.tz,
    month: "long"
  });
  const year = date.getFullYear().toString();
  return { time, day, month, year };
};

// src/renderers/uplot-utils.ts
var MIDNIGHT_TIMESTAMP = "00:00";
var seriesColors = [
  "#7b56db",
  "#0089cf",
  "#dd9900",
  "#ff677b",
  "#cb2196",
  "#813193",
  "#0051b5",
  "#008c80",
  "#99b100"
];
var { bars } = uplot_default.paths;
var bars90PercentGap100MaxWidthPaths = bars ? bars({ size: [0.9, 100] }) : void 0;
var generateSeries = (field, seriesIdx, config, show) => {
  if (seriesIdx === 0) {
    return {
      label: "_time",
      key: "_time"
    };
  }
  if (!config) {
    return {
      key: field,
      label: field,
      spanGaps: true,
      stroke: seriesColors[(seriesIdx - 1) % seriesColors.length]
    };
  }
  const label = config.label || field;
  const color = config.color || seriesColors[(seriesIdx - 1) % seriesColors.length];
  const overrides = config.overrides || {};
  switch (config.type) {
    case "area": {
      return __spreadValues({
        show,
        key: field,
        label,
        stroke: color,
        fill: color,
        scale: config.scale,
        spanGaps: true
      }, overrides);
    }
    case "points":
      return __spreadValues({
        show,
        key: field,
        paths: () => null,
        points: config.pointSize ? {
          space: 0,
          size: config.pointSize,
          fill: color
        } : { space: 0 },
        label,
        stroke: color,
        fill: color,
        scale: config.scale,
        spanGaps: false
      }, overrides);
    case "bar":
      return __spreadValues({
        show,
        key: field,
        label,
        stroke: color,
        fill: color,
        scale: config.scale,
        spanGaps: true,
        paths: bars90PercentGap100MaxWidthPaths
      }, overrides);
    case "stacked-bar":
      return __spreadValues({
        show,
        key: field,
        label,
        stroke: color,
        fill: color,
        scale: config.scale,
        spanGaps: true,
        paths: bars90PercentGap100MaxWidthPaths,
        negY: false,
        points: {
          show: false
        },
        stacking: {
          mode: "normal",
          group: "A"
        }
      }, overrides);
    case "stacked-area":
      return __spreadValues({
        show,
        key: field,
        label,
        stroke: color,
        fill: color,
        scale: config.scale,
        spanGaps: true,
        negY: false,
        points: {
          show: false
        },
        stacking: {
          mode: "normal",
          group: "A"
        }
      }, overrides);
    case "line":
    default:
      return __spreadValues({
        show,
        key: field,
        label,
        stroke: color,
        fill: void 0,
        scale: config.scale,
        spanGaps: true,
        points: {
          show: config.hidePoints !== void 0 ? !config.hidePoints : void 0
        }
      }, overrides);
  }
};
var PLOT_TYPES_TO_EXPAND_RANGE = ["bar", "stacked-bar"];
var mapDSToSeries = (fields, seriesConfig = {}, scaleConfig = {}, hiddenSeries) => fields.map((field, index) => {
  const mergedSeriesConfig = getMergedSeriesConfigForField(seriesConfig, scaleConfig, field);
  const showSeries = !(hiddenSeries == null ? void 0 : hiddenSeries.includes(field));
  return generateSeries(field, index, mergedSeriesConfig, showSeries);
});
var getMaxRangeValue = (numberOfDatapoints, max, range) => {
  if (range) {
    return numberOfDatapoints < 2 ? range.max : Math.max(max, range.max);
  }
  return max;
};
var isTimeSeriesData = (dataSet) => dataSet && dataSet.fields[0] && dataSet.fields[0] === "_time";
var mapDSToScales = (seriesConfig = {}, scaleConfig = {}, range, isTimeSeries = true) => {
  const mergedSeriesConfig = getMergedSeriesConfig(seriesConfig, scaleConfig);
  return Object.assign(
    {
      x: {
        time: !!isTimeSeries,
        range: (u, min, max) => {
          if (isTimeSeries === false) {
            return [0, u.data[0].length - 1];
          }
          const shouldExpandRange = some_default(
            mergedSeriesConfig,
            (v) => exists(v.type) && PLOT_TYPES_TO_EXPAND_RANGE.includes(v.type)
          );
          const minValue = range ? Math.min(min, range.min) : min;
          const maxValue = getMaxRangeValue(u.data[0].length, max, range);
          if (shouldExpandRange && u.data[0].length) {
            const dailyBarWidth = !!range && range.dailyResolution;
            const width = maxValue - minValue;
            const barWidth = dailyBarWidth ? DAY : width / u.data[0].length;
            const offset = barWidth / 2;
            return [minValue - offset, maxValue + offset];
          }
          return [minValue, maxValue];
        }
      }
    },
    ...Object.keys(scaleConfig).map((key) => ({
      [key]: {
        distr: scaleConfig[key].type === "log" ? 3 : 1,
        range: scaleConfig[key].range
      }
    }))
  );
};
var mapScalesToAxes = (xAxisResolution, theme, scaleConfig = {}, locale, hideXAxis, range, isTimeSeries = true, rawXaxisValues = [], timestampFormat = "compact") => {
  const showOnlyRangeValues = !!range && range.dailyResolution;
  const xAxesScaleConfig = {
    show: !hideXAxis,
    font: theme.font,
    stroke: theme.axis.xLabelStroke,
    grid: {
      show: false
    },
    ticks: {
      width: 1,
      stroke: theme.axis.gridStroke
    },
    incrs: !isTimeSeries ? [1] : void 0,
    values: (_self, splits) => {
      var _a;
      const xRange = splits[splits.length - 1] - splits[0];
      let lastDay = "";
      let lastYear = "";
      let lastMonth = "";
      const tickInterval = splits.length > 2 ? getTickInterval((splits[1] - splits[0]) * 1e3) : "1d";
      const defaultLocale = {
        tz: locale.tz,
        twelveHourTimeFormat: (_a = locale.twelveHourTimeFormat) != null ? _a : true
      };
      return splits.map((v, idx) => {
        if (!isTimeSeries) {
          return rawXaxisValues && rawXaxisValues[v] ? rawXaxisValues[v].toString() : "";
        }
        const millisecondsEpoch = v * SECOND_TO_MILLISECOND;
        const timestampString = formatTimestamp(millisecondsEpoch, "timeCompact", {
          tz: locale.tz
        });
        const labelParts = [];
        if (timestampFormat === "expanded") {
          const { time, day, month, year } = getDefaultExpandedFormatTimeStampLabelParts(
            millisecondsEpoch,
            tickInterval,
            locale
          );
          if (tickInterval !== "1d" && tickInterval !== "7d" && tickInterval !== "1mo") {
            labelParts.push(time);
          }
          if (tickInterval !== "1mo" && (idx === 0 || day !== lastDay && lastDay.indexOf(day) < 0)) {
            labelParts.push(day);
            lastDay = day;
          }
          if (tickInterval === "1mo" && month !== lastMonth) {
            labelParts.push(month);
            lastMonth = month;
          }
          if (idx === 0 || year !== lastYear) {
            labelParts.push(year);
            lastYear = year;
          }
          return labelParts.join("\n");
        }
        if (timestampFormat === "compact") {
          const isItMidnight = timestampString === MIDNIGHT_TIMESTAMP;
          const isItMoreThanADay = xRange >= X_AXIS_TIME_OPTIONS["1Day"];
          const isItLessThanADay = xRange < X_AXIS_TIME_OPTIONS["1Day"];
          if (showOnlyRangeValues) {
            return formatTimestamp(millisecondsEpoch, "dateVerbose", defaultLocale);
          }
          if (isItMoreThanADay && isItMidnight || isItLessThanADay && isItMidnight) {
            return formatTimestamp(millisecondsEpoch, "dateCompact", defaultLocale);
          }
          if (isItLessThanADay) {
            return formatTimestamp(millisecondsEpoch, "timeCompact", defaultLocale);
          }
        }
        return null;
      });
    },
    splits: showOnlyRangeValues ? [range.min, range.max] : void 0
  };
  if (timestampFormat === "expanded") {
    xAxesScaleConfig.space = 60;
    xAxesScaleConfig.align = 1;
  }
  return [
    xAxesScaleConfig,
    // default
    ...Object.keys(scaleConfig).length === 0 ? [
      {
        font: theme.font,
        stroke: theme.axis.yLabelStroke,
        labelFont: theme.labelFont,
        grid: {
          stroke: theme.axis.gridStroke,
          width: 1
        },
        ticks: {
          show: false
        }
      }
    ] : [],
    // custom
    ...Object.keys(scaleConfig).map((key) => ({
      scale: key,
      label: scaleConfig[key].label,
      labelFont: theme.labelFont,
      font: theme.font,
      stroke: theme.axis.yLabelStroke,
      side: scaleConfig[key].side === "right" ? 1 : 3,
      size: scaleConfig[key].width || 55,
      grid: {
        show: exists(scaleConfig[key].showGrid) ? scaleConfig[key].showGrid : true,
        stroke: theme.axis.gridStroke,
        width: 1
      },
      ticks: {
        show: false
      },
      values: scaleConfig[key].tickFmt ? (_, splits) => splits.map((v) => {
        if (v === null) {
          return null;
        }
        const config = scaleConfig[key];
        return exists(config) ? formatValueWithScaleConfig(v, config, xAxisResolution) : v.toString();
      }) : void 0
    }))
  ];
};
function stackData(series, _data) {
  var _a;
  if (!series.some((s) => exists(s.stacking))) {
    return { data: _data, bands: void 0 };
  }
  const data = Array(series.length);
  const bands = [];
  const dataLen = ((_a = _data[0]) == null ? void 0 : _a.length) || 0;
  const zeroArr = Array(dataLen).fill(0);
  const stackGroups = /* @__PURE__ */ new Map();
  const seriesStackKeys = Array(series.length);
  series.forEach((s, si) => {
    const vals = _data[si].slice();
    if (s.negY) {
      for (let i = 0; i < vals.length; i += 1) {
        const value = vals[i] || 0;
        vals[i] = value * -1;
      }
    }
    if (s.stacking && s.stacking.mode !== "none") {
      const hasPos = vals.some((v) => (v || 0) > 0);
      const stackKey = (
        // s.stacking.mode + s.scaleKey + s.stacking.group + (hasPos ? '+' : '-'));
        s.stacking.mode + s.stacking.group + (hasPos ? "+" : "-")
      );
      seriesStackKeys[si] = stackKey;
      let group = stackGroups.get(stackKey);
      if (!exists(group)) {
        group = {
          series: [],
          acc: zeroArr.slice(),
          dir: hasPos ? -1 : 1
        };
        stackGroups.set(stackKey, group);
      }
      group.series.unshift(si);
      data[si] = Array(dataLen);
      const stacked = data[si];
      const { acc } = group;
      for (let i = 0; i < dataLen; i += 1) {
        const v = vals[i];
        if (v != null) {
          acc[i] += v;
          stacked[i] = acc[i];
        } else {
          stacked[i] = v;
        }
      }
    } else {
      data[si] = vals;
    }
  });
  series.forEach((s, si) => {
    if (s.stacking && s.stacking.mode === "percent") {
      const group = stackGroups.get(seriesStackKeys[si]);
      if (exists(group)) {
        const sign = group.dir * -1;
        const stacked = data[si];
        for (let i = 0; i < dataLen; i += 1) {
          const v = stacked[i];
          if (v != null) {
            stacked[i] = sign * (v / group.acc[i]);
          }
        }
      }
    }
  });
  stackGroups.forEach((group) => {
    const { series: groupSeries, dir } = group;
    const lastIdx = groupSeries.length - 1;
    groupSeries.forEach((si, i) => {
      if (i !== lastIdx) {
        const nextIdx = groupSeries[i + 1];
        bands.push({
          series: [si, nextIdx],
          dir
        });
      }
    });
  });
  return {
    data,
    bands
  };
}
function getSeriesKey(seriesIndex, allSeries) {
  return typeof seriesIndex === "number" && seriesIndex < (allSeries == null ? void 0 : allSeries.length) ? allSeries[seriesIndex].field : void 0;
}

export {
  uplot_default,
  uplot_exports,
  some_default,
  some_exports,
  mapDSToSeries,
  isTimeSeriesData,
  mapDSToScales,
  mapScalesToAxes,
  stackData,
  getSeriesKey,
  SECOND_TO_MICROSECOND,
  DAY,
  exists,
  isNumber,
  useDynamicCallback,
  useCreateAttachedDivElement,
  getMergedSeriesConfigForField,
  getXAxisResolution,
  formatValueWithSeriesConfig,
  formatValueForPlottingWithSeriesConfig,
  findClosest,
  buildColorFunction,
  timeTickFormatter,
  filterSplit,
  roundToPoT,
  pixelStrToNum,
  markPrefix,
  buildSeriesForLegend
};
//# sourceMappingURL=chunk-6N4JNZ5S.js.map
