import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import _typeof from '@babel/runtime/helpers/typeof';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import mapValues from '../node_modules/lodash-es/mapValues.js';
import isNil from '../node_modules/lodash-es/isNil.js';
import isEmpty from '../node_modules/lodash-es/isEmpty.js';
import 'core-js/modules/es.symbol.js';
import 'core-js/modules/es.array.concat.js';
import 'core-js/modules/es.array.filter.js';
import 'core-js/modules/es.array.find.js';
import 'core-js/modules/es.array.find-index.js';
import 'core-js/modules/es.array.includes.js';
import 'core-js/modules/es.array.iterator.js';
import 'core-js/modules/es.array.join.js';
import 'core-js/modules/es.array.map.js';
import 'core-js/modules/es.array-buffer.slice.js';
import 'core-js/modules/es.number.is-integer.js';
import 'core-js/modules/es.object.entries.js';
import 'core-js/modules/es.object.get-own-property-descriptor.js';
import 'core-js/modules/es.object.get-own-property-descriptors.js';
import 'core-js/modules/es.object.keys.js';
import 'core-js/modules/es.object.to-string.js';
import 'core-js/modules/es.promise.js';
import 'core-js/modules/es.regexp.constructor.js';
import 'core-js/modules/es.regexp.exec.js';
import 'core-js/modules/es.regexp.to-string.js';
import 'core-js/modules/es.set.js';
import 'core-js/modules/es.string.includes.js';
import 'core-js/modules/es.string.iterator.js';
import 'core-js/modules/es.string.match.js';
import 'core-js/modules/es.string.replace.js';
import 'core-js/modules/es.typed-array.uint8-array.js';
import 'core-js/modules/es.typed-array.copy-within.js';
import 'core-js/modules/es.typed-array.every.js';
import 'core-js/modules/es.typed-array.fill.js';
import 'core-js/modules/es.typed-array.filter.js';
import 'core-js/modules/es.typed-array.find.js';
import 'core-js/modules/es.typed-array.find-index.js';
import 'core-js/modules/es.typed-array.for-each.js';
import 'core-js/modules/es.typed-array.includes.js';
import 'core-js/modules/es.typed-array.index-of.js';
import 'core-js/modules/es.typed-array.iterator.js';
import 'core-js/modules/es.typed-array.join.js';
import 'core-js/modules/es.typed-array.last-index-of.js';
import 'core-js/modules/es.typed-array.map.js';
import 'core-js/modules/es.typed-array.reduce.js';
import 'core-js/modules/es.typed-array.reduce-right.js';
import 'core-js/modules/es.typed-array.reverse.js';
import 'core-js/modules/es.typed-array.set.js';
import 'core-js/modules/es.typed-array.slice.js';
import 'core-js/modules/es.typed-array.some.js';
import 'core-js/modules/es.typed-array.sort.js';
import 'core-js/modules/es.typed-array.subarray.js';
import 'core-js/modules/es.typed-array.to-locale-string.js';
import 'core-js/modules/es.typed-array.to-string.js';
import 'core-js/modules/web.dom-collections.for-each.js';
import 'core-js/modules/web.dom-collections.iterator.js';
import React__default, { useState, useMemo } from 'react';
import warning from 'warning';
import { CARD_SIZES, CARD_TYPES, BAR_CHART_TYPES } from '../constants/LayoutConstants.js';
import dayjs, { DAYJS_INPUT_FORMATS } from './dayjs.js';
import { convertStringsToDOMElement } from './componentUtilityFunctions.js';

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }

/**
 * determine time range from drop down action
 * range - requested range from card dropdown action
 */
var determineCardRange = function determineCardRange(range) {
  switch (range) {
    case 'last24Hours':
      return {
        interval: 'day',
        count: -1,
        timeGrain: 'hour',
        type: 'rolling'
      };
    case 'last7Days':
      return {
        interval: 'week',
        count: -1,
        timeGrain: 'day',
        type: 'rolling'
      };
    case 'lastMonth':
      return {
        interval: 'month',
        count: -1,
        timeGrain: 'day',
        type: 'rolling'
      };
    case 'lastQuarter':
      return {
        interval: 'quarter',
        count: -1,
        timeGrain: 'month',
        type: 'rolling'
      };
    case 'lastYear':
      return {
        interval: 'year',
        count: -1,
        timeGrain: 'month',
        type: 'rolling'
      };
    case 'thisWeek':
      return {
        interval: 'week',
        count: -1,
        timeGrain: 'day',
        type: 'periodToDate'
      };
    case 'thisMonth':
      return {
        interval: 'month',
        count: -1,
        timeGrain: 'day',
        type: 'periodToDate'
      };
    case 'thisQuarter':
      return {
        interval: 'quarter',
        count: -1,
        timeGrain: 'month',
        type: 'periodToDate'
      };
    case 'thisYear':
      return {
        interval: 'year',
        count: -1,
        timeGrain: 'month',
        type: 'periodToDate'
      };
    default:
      return {
        interval: 'day',
        count: -5,
        timeGrain: 'day',
        type: 'rolling'
      };
  }
};

/** Compare grains to decide which is greater */
var compareGrains = function compareGrains(grain1, grain2) {
  var greaterGrains = {
    hour: ['day', 'week', 'month', 'year'],
    day: ['week', 'month', 'year'],
    week: ['month', 'year'],
    month: ['year'],
    year: []
  };
  if (grain1 === grain2) {
    return 0;
  }
  if (!grain1 || greaterGrains[grain1].includes(grain2)) {
    return -1;
  }
  return 1;
};
var getUpdatedCardSize = function getUpdatedCardSize(oldSize) {
  var changedSize = oldSize === 'XSMALLWIDE' ? 'SMALLWIDE' : oldSize === 'WIDE' ? 'MEDIUMWIDE' : oldSize === 'TALL' ? 'LARGETHIN' : oldSize === 'XLARGE' ? 'LARGEWIDE' : null;
  var newSize = oldSize;
  if (changedSize) {
    {
      warning(false, "You have set your card to a ".concat(oldSize, " size. This size name is deprecated. The card will be displayed as a ").concat(changedSize, " size.")) ;
    }
    newSize = changedSize;
  }
  return newSize;
};

/**
 * This function provides decimal precision and compact abbreviation formatting for number values
 * @param {number} value, the value the card will display
 * @param {number} precision, how many decimal values to display configured at the attribute level
 * @param {string} locale, the local browser locale because locales use different decimal separators
 * @param {Boolean} isNumberValueCompact whether the number should be abbreviated (i.e. 10,000 = 10K)
 */
var formatNumberWithPrecision = function formatNumberWithPrecision(value, precision) {
  var locale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'en';
  var isNumberValueCompact = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
  return new Intl.NumberFormat(locale, _objectSpread(_objectSpread({}, precision ? {
    minimumFractionDigits: precision,
    maximumFractionDigits: precision
  } : {}), isNumberValueCompact ? {
    notation: 'compact'
  } : {})).format(value);
};

/**
 * Reusable function to check if a string contains variables identified by surrounding curly braces i.e. {deviceid}
 * @param {string} value A string with variables, i.e. `{manufacturer} acceleration over the last {sensor} hours`
 * @returns {Array<String>} an array of variables, i.e. ['manufacturer', 'sensor']
 */
var getVariables = function getVariables(value) {
  var _variables;
  var variables = value && typeof value === 'string' ? value.match(/{[a-zA-Z0-9_-]+}/g) : null;
  variables = (_variables = variables) === null || _variables === void 0 ? void 0 : _variables.map(function (variable) {
    return variable.replace(/[{}]/g, '');
  });
  return variables;
};

/**
 * Replace variables from the list of variables that are found on the target with their corresponding value
 * @param {Array<String>} variables an array of variable strings
 * @param {object} cardVariables an object with properties such that the key is a variable name and the value is the value to replace it with, i.e. { manufacturer: 'Rentech', sensor: 3 }
 * @param {Object || Array || String} target a card or string to replace variables on
 * @returns {Object} a parsed object with all variables replaced with their corresponding values found on the values object
 */
var replaceVariables = function replaceVariables(variables, cardVariables, target) {
  // Need to create a copy of cardVariables with all lower-case keys
  var insensitiveCardVariables = Object.keys(cardVariables).reduce(function (acc, variable) {
    acc[variable.toLowerCase()] = cardVariables[variable];
    return acc;
  }, {});

  // if it's an array then recursively place the variables in each element
  if (Array.isArray(target)) {
    return target.map(function (element) {
      return replaceVariables(variables, cardVariables, element);
    });
  }

  // if it's an object, then recursively replace each value unless it's a react element
  if (_typeof(target) === 'object') {
    // if it's a react element, leave it alone
    return /*#__PURE__*/React__default.isValidElement(target) || isNil(target) ? target : mapValues(target, function (property) {
      return replaceVariables(variables, insensitiveCardVariables, property);
    });
  }

  // we can only replace on string targets at this point
  if (typeof target !== 'string') {
    return target;
  }
  var updatedTarget = target;
  variables.forEach(function (variable) {
    var insensitiveVariable = variable.toLowerCase();
    var variableRegex = new RegExp("{".concat(variable, "}"), 'g');
    var exactMatch = new RegExp("^{".concat(insensitiveVariable, "}$"), 'g');
    // if we're an exact match on number then set to number (to support numeric thresholds)
    if (exactMatch.test(target) && typeof insensitiveCardVariables[insensitiveVariable] === 'number') {
      updatedTarget = insensitiveCardVariables[insensitiveVariable];
    } else if (typeof insensitiveCardVariables[insensitiveVariable] === 'function') {
      var callback = insensitiveCardVariables[insensitiveVariable];
      updatedTarget = callback(variable, target);
    } else {
      // if the target is still a string then continue
      updatedTarget = typeof updatedTarget === 'string' && !isNil(insensitiveCardVariables[insensitiveVariable]) ? updatedTarget.replace(variableRegex, insensitiveCardVariables[insensitiveVariable]) : updatedTarget;
    }
  });
  return updatedTarget;
};

/**
 * This function recurses across all of the card properties to find templatted variable
 * strings that need to be replaced
 * @param {Object} cardProperty i.e. title, content
 * @param {Array<string>} keysToSkip if present, do not attempt to retrieve variables
 * i.e. in table cards, there is unique cases in which it retrieves its only variables
 * @returns {Array<String>} an array of unique variable values
 */
var getCardVariables = function getCardVariables(cardProperty) {
  var keysToSkip = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  var cardVariables = Object.entries(cardProperty).reduce(function (acc, _ref) {
    var _ref2 = _slicedToArray(_ref, 2),
      key = _ref2[0],
      value = _ref2[1];
    if (_typeof(value) === 'object' && ! /*#__PURE__*/React__default.isValidElement(value) && !isNil(value)) {
      // recursively search any objects for additional string properties
      acc.push.apply(acc, _toConsumableArray(getCardVariables(value, keysToSkip)));
    } else if (typeof value === 'string' && !keysToSkip.includes(key)) {
      // if it's a string, look for variables
      var detectedVariables = getVariables(value);
      if (detectedVariables) {
        acc.push.apply(acc, _toConsumableArray(detectedVariables));
      }
    }
    return acc;
  }, []);
  return _toConsumableArray(new Set(cardVariables));
};

/**
 * Replace variables from the list of variables that are found on the target with their corresponding value
 * @param {string} title - Title for the card
 * @param {object} content - Contents for the card
 * @param {string} values - Values for the card
 * @param {object} card - The rest of the card
 * @param {Array<string>} keysToSkip if present, do not attempt to retrieve variables
 * i.e. in table cards, there is unique cases in which it retrieves its only variables
 * @return {object} updatedCard - card with any found variables replaced by their coresponding values, or the original card if no variables
 */
var handleCardVariables = function handleCardVariables(title, content, values, card) {
  var keysToSkip = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
  var updatedCard = _objectSpread({
    title: title,
    content: content,
    values: values
  }, card);
  if (!updatedCard.cardVariables) {
    return updatedCard;
  }
  var cardVariables = updatedCard.cardVariables;
  var variablesArray = getCardVariables(updatedCard, keysToSkip);
  return replaceVariables(variablesArray, cardVariables, updatedCard);
};

/**
 * Determines how many decimals to show for a value based on the value, the available size of the card
 * @param {string} size constant that describes the size of the Table card
 * @param {any} value will be checked to determine how many decimals to show
 * @param {*} precision Desired decimal precision, will be used if specified
 */
var determinePrecision = function determinePrecision(size, value, precision) {
  // If it's an integer don't return extra values
  if (Number.isInteger(value)) {
    return 0;
  }
  // If the card is small we don't have room for decimals!
  switch (size) {
    case CARD_SIZES.SMALL:
      return !isNil(precision) ? precision : Math.abs(value) > 9 ? 0 : undefined;
  }
  return precision;
};

/**
 * Determines how to format our values for our lines and bars
 *
 * @param {any} value any value possible, but will only special format if a number
 * @param {string} size card size
 * @param {string} unit any optional units to show
 * @param {number} the selected precision value
 */
var chartValueFormatter = function chartValueFormatter(value, size, unit, locale, precision) {
  var precisionToFormat = precision || determinePrecision(size, value, Math.abs(value) > 1 ? 1 : 3);
  var renderValue = value;
  if (typeof value === 'number') {
    renderValue = formatNumberWithPrecision(value, precisionToFormat, locale);
  } else if (isNil(value)) {
    renderValue = '--';
  }
  return "".concat(renderValue).concat(!isNil(unit) ? " ".concat(unit) : '');
};

/**
 * Charts render incorrectly if size is too small, so change their size to MEDIUM
 * @param {string} size card size
 */
var increaseSmallCardSize = function increaseSmallCardSize(size, cardName) {
  {
    warning(size !== CARD_SIZES.SMALL && size !== CARD_SIZES.SMALLWIDE && size !== CARD_SIZES.SMALLFULL, "".concat(cardName, " does not support card size ").concat(size)) ;
  }
  return size === CARD_SIZES.SMALL ? CARD_SIZES.MEDIUM : size === CARD_SIZES.SMALLWIDE ? CARD_SIZES.MEDIUMWIDE : size === CARD_SIZES.SMALLFULL ? CARD_SIZES.MEDIUMWIDE : size;
};
var resizeHandleId = 'resizableHandle';

/**
 * Simple helper function to extract the resizeHandles from the react children
 * @param {} children the react children data structure containing the resizeHandles
 */
var getResizeHandles = function getResizeHandles(children) {
  return React__default.Children.toArray(children).filter(function (child) {
    var _child$key;
    return (_child$key = child.key) === null || _child$key === void 0 ? void 0 : _child$key.includes(resizeHandleId);
  });
};

/**
 * Custom hook that manages the isResizable state. It does that by wrapping
 * the onStart/onStop callbacks found in the resizeHandles. The resizeHandles
 * are created by the external library react-grid-layout.
 *
 * The hook returns an object with both the modified resizeHandles and
 * the isResizing state.
 *
 * @param {array} wrappingCardResizeHandles resizeHandles optionally passed down by wrapping card
 * @param {} children the react children data structure containing the resizeHandles
 * @param {boolean} isResizable true if the component using the hook should be resizable
 */
var useCardResizing = function useCardResizing(wrappingCardResizeHandles, children, isResizable) {
  var _useState = useState(false),
    _useState2 = _slicedToArray(_useState, 2),
    isResizing = _useState2[0],
    setIsResizing = _useState2[1];
  var resizeHandlesWithEventHandling = useMemo(function () {
    var resizeHandles = wrappingCardResizeHandles || isResizable && getResizeHandles(children) || [];
    return resizeHandles.map(function (handleElement) {
      return /*#__PURE__*/React__default.cloneElement(handleElement, _objectSpread(_objectSpread({}, handleElement.props), {}, {
        onStart: function onStart() {
          var _handleElement$props;
          setIsResizing(true);
          if ((_handleElement$props = handleElement.props) !== null && _handleElement$props !== void 0 && _handleElement$props.onStart) {
            var _handleElement$props2;
            (_handleElement$props2 = handleElement.props).onStart.apply(_handleElement$props2, arguments);
          }
        },
        disabled: false,
        onStop: function onStop() {
          var _handleElement$props3;
          setIsResizing(false);
          if ((_handleElement$props3 = handleElement.props) !== null && _handleElement$props3 !== void 0 && _handleElement$props3.onStop) {
            var _handleElement$props4;
            (_handleElement$props4 = handleElement.props).onStop.apply(_handleElement$props4, arguments);
          }
        }
      }));
    });
  },
  // eslint-disable-next-line react-hooks/exhaustive-deps
  [isResizable]);
  return {
    resizeHandles: resizeHandlesWithEventHandling,
    isResizing: isResizing
  };
};

/**
 *
 * @param {string} url the url where the image is hosted
 * @param {function} callback for handling errors from fetch
 */
var fetchDataURL = function fetchDataURL(url, callback) {
  return fetch(url).then(function (res) {
    if (!res.ok) {
      throw Error(res.statusText);
    }
    return res.arrayBuffer();
  }).then(function (ab) {
    return {
      files: {
        addedFiles: [new File([ab], "".concat(url.match(/([^/]*?)(?=\?|#|$)/)[0]))]
      },
      dataURL: "data:image/png;base64,".concat(btoa(new Uint8Array(ab).reduce(function (data, byte) {
        return data + String.fromCharCode(byte);
      }, '')))
    };
  }).catch(function (e) {
    return callback(e.message);
  });
};

/**
 * Returns an array of matching thresholds will only return the highest severity threshold for a column
 * If passed a columnId, it filters the threshold check on the current column only
 * @param {Array<Object>} thresholds
 * @param {Object} item
 * @param {string} columnId
 * @returns {Array} matching thresholds
 */
var findMatchingThresholds = function findMatchingThresholds(thresholds, item, columnId) {
  if (!item) {
    return [];
  }
  return thresholds.filter(function (t) {
    var comparison = t.comparison,
      value = t.value,
      dataSourceId = t.dataSourceId;
    // Does the threshold apply to the current column?
    if (columnId && !columnId.includes(dataSourceId)) {
      return false;
    }
    switch (comparison) {
      case '<':
        return !isNil(item[dataSourceId]) && parseFloat(item[dataSourceId]) < value;
      case '>':
        return parseFloat(item[dataSourceId]) > value;
      case '=':
        return parseFloat(item[dataSourceId]) === value || item[dataSourceId] === value;
      // need to handle the string case
      case '<=':
        return !isNil(item[dataSourceId]) && parseFloat(item[dataSourceId]) <= value;
      case '>=':
        return parseFloat(item[dataSourceId]) >= value;
      default:
        return false;
    }
  }).reduce(function (highestSeverityThreshold, threshold) {
    var currentThresholdIndex = highestSeverityThreshold.findIndex(function (currentThreshold) {
      return currentThreshold.dataSourceId === threshold.dataSourceId;
    });
    if (
    // If I don't have a threshold currently for this column
    currentThresholdIndex < 0) {
      highestSeverityThreshold.push(_objectSpread(_objectSpread({}, threshold), {}, {
        currentValue: item[threshold.dataSourceId]
      }));
    } // The lowest severity is actually the most severe
    else if (highestSeverityThreshold[currentThresholdIndex].severity > threshold.severity) {
      // eslint-disable-next-line no-param-reassign
      highestSeverityThreshold[currentThresholdIndex] = _objectSpread(_objectSpread({}, threshold), {}, {
        currentValue: item[threshold.dataSourceId]
      });
    }
    return highestSeverityThreshold;
  }, []);
};

/** compare the current datapoint to a list of alert ranges */
var findMatchingAlertRange = function findMatchingAlertRange(alertRanges, data) {
  var currentData = Array.isArray(data) ? data[0] : data;
  var _ref3 = currentData || {},
    currentDataPoint = _ref3.date,
    dataSourceId = _ref3.dataSourceId;
  if (!currentDataPoint) {
    return [];
  }
  var currentDatapointTimestamp = currentDataPoint.valueOf();
  return Array.isArray(alertRanges) && alertRanges.filter(function (alert) {
    var _alert$inputSource;
    return currentDatapointTimestamp <= alert.endTimestamp && currentDatapointTimestamp >= alert.startTimestamp && (alert !== null && alert !== void 0 && (_alert$inputSource = alert.inputSource) !== null && _alert$inputSource !== void 0 && _alert$inputSource.dataSourceIds && dataSourceId // If there is input data sources provided use them to do the filter
    ? alert.inputSource.dataSourceIds.includes(dataSourceId) : true);
  });
};

/**
 * Extends default tooltip with the additional date information, and optionally alert information
 * @param {object} dataOrHoveredElement data object for this particular datapoint should have a date field containing the timestamp
 * @param {string} defaultTooltip Default HTML generated for this tooltip that needs to be marked up
 * @param {object} _datum of the hovered element
 * @param {array} alertRanges Array of alert range information to search
 * @param {string} alertDetected Translated string to indicate that the alert is detected
 * @param {bool} showTimeInGMT
 * @param {string} tooltipDateFormatPattern
 * @returns {string} DOM representation of the tooltip
 */
var handleTooltip = function handleTooltip(dataOrHoveredElement, defaultTooltip, _datum, alertRanges, alertDetected, showTimeInGMT) {
  var _data$, _data$date;
  var tooltipDateFormatPattern = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : DAYJS_INPUT_FORMATS.SECONDS;
  var locale = arguments.length > 7 ? arguments[7] : undefined;
  dayjs.locale(locale);
  var data = /* eslint-disable no-underscore-dangle */dataOrHoveredElement !== null && dataOrHoveredElement !== void 0 && dataOrHoveredElement.__data__ ? dataOrHoveredElement.__data__ // eslint-disable-line no-underscore-dangle
  : dataOrHoveredElement;
  var timeStamp = Array.isArray(data) ? (_data$ = data[0]) === null || _data$ === void 0 || (_data$ = _data$.date) === null || _data$ === void 0 ? void 0 : _data$.getTime() : data === null || data === void 0 || (_data$date = data.date) === null || _data$date === void 0 ? void 0 : _data$date.getTime();
  var dateLabel = timeStamp ? "<li class='datapoint-tooltip'>\n        <p class='label'>".concat((showTimeInGMT // show timestamp in gmt or local time
  ? dayjs.utc(timeStamp) : dayjs.tz(timeStamp)).format(tooltipDateFormatPattern), "</p>\n      </li>") : '';
  var matchingAlertRanges = findMatchingAlertRange(alertRanges, data);
  var matchingAlertLabels = Array.isArray(matchingAlertRanges) ? matchingAlertRanges.map(function (matchingAlertRange) {
    return "<li class='datapoint-tooltip'><a style=\"background-color:".concat(matchingAlertRange.color, "\" class=\"tooltip-color\"></a><p class='label'>").concat(alertDetected, " ").concat(matchingAlertRange.details, "</p></li>");
  }).join('') : '';

  // Convert strings to DOM Elements so we can easily reason about them and manipulate/replace pieces.
  var _convertStringsToDOME = convertStringsToDOMElement([defaultTooltip, dateLabel, matchingAlertLabels]),
    _convertStringsToDOME2 = _slicedToArray(_convertStringsToDOME, 3),
    defaultTooltipDOM = _convertStringsToDOME2[0],
    dateLabelDOM = _convertStringsToDOME2[1],
    matchingAlertLabelsDOM = _convertStringsToDOME2[2];

  // if the data has no timestamp, there will no dateLabel
  // and without this check a null string was being inserted into the DOM.
  if (dateLabelDOM.querySelector('li')) {
    // The first <li> will always be carbon chart's Dates row in this case, replace with our date format <li>
    defaultTooltipDOM.querySelector('li:first-child').replaceWith(dateLabelDOM.querySelector('li'));
  }

  // Append all the matching alert labels
  matchingAlertLabelsDOM.querySelectorAll('li').forEach(function (label) {
    defaultTooltipDOM.querySelector('ul').append(label);
  });
  return defaultTooltipDOM.innerHTML;
};

/** Determind whether a card displays time based data */
var isTimeBasedCard = function isTimeBasedCard(card) {
  var _card$content, _card$content2, _card$content3, _card$content4, _card$content5;
  return card.type === CARD_TYPES.TIMESERIES || card.type === CARD_TYPES.TABLE && ((_card$content = card.content) === null || _card$content === void 0 || (_card$content = _card$content.columns) === null || _card$content === void 0 ? void 0 : _card$content.find(function (column) {
    return column.type === 'TIMESTAMP';
  })) || ((_card$content2 = card.content) === null || _card$content2 === void 0 ? void 0 : _card$content2.type) === BAR_CHART_TYPES.SIMPLE && ((_card$content3 = card.content) === null || _card$content3 === void 0 ? void 0 : _card$content3.timeDataSourceId) || ((_card$content4 = card.content) === null || _card$content4 === void 0 ? void 0 : _card$content4.type) === BAR_CHART_TYPES.STACKED && ((_card$content5 = card.content) === null || _card$content5 === void 0 ? void 0 : _card$content5.timeDataSourceId);
};

/**
 * Get translated label or title from i18n object, fallback to original if not found
 * @param {string} label - The label or title key to translate
 * @param {boolean} shouldUseTranslatedLabels - Flag to determine if translation should be used
 * @param {Object} i18n - The i18n object containing translations
 * @returns {string} - The translated label or original label if translation not found
 */
var getTranslatedLabel = function getTranslatedLabel(label, shouldUseTranslatedLabels, i18n) {
  if (!isEmpty(label) && shouldUseTranslatedLabels && i18n && i18n[label]) {
    return i18n[label];
  }
  return label;
};

export { chartValueFormatter, compareGrains, determineCardRange, determinePrecision, fetchDataURL, findMatchingAlertRange, findMatchingThresholds, formatNumberWithPrecision, getCardVariables, getResizeHandles, getTranslatedLabel, getUpdatedCardSize, getVariables, handleCardVariables, handleTooltip, increaseSmallCardSize, isTimeBasedCard, replaceVariables, useCardResizing };
