"use strict";

const chartExportOptions = {
  buttons: {
    contextButton: {
      menuItems: ["downloadPNG", "downloadJPEG", "downloadPDF", "downloadSVG"],
    },
  },
};

/**
 * Convert a hexadecimal color code obtained from the Highcharts object (`Highcharts.getOptions().colors`) to its equivalent RGB color code
 * @param {String} hexCode Input hex color code
 * @returns {String} Output RGB color code
 */
const convertHexColorToRGBColor = function (hexCode) {
  const hexToRGBMapping = {
    "#7cb5ec": "rgb(124, 181, 236)",
    "#434348": "rgb(67, 67, 72)",
    "#90ed7d": "rgb(144, 237, 125)",
    "#f7a35c": "rgb(247, 163, 92)",
    "#8085e9": "rgb(128, 133, 233)",
    "#f15c80": "rgb(241, 92, 128)",
    "#e4d354": "rgb(228, 211, 84)",
    "#2b908f": "rgb(228, 211, 84)",
    "#f45b5b": "rgb(244, 91, 91)",
    "#91e8e1": "rgb(145, 232, 225)",
  };

  if (hexToRGBMapping?.[hexCode] === undefined)
    throw new Error(
      "The provided hex code is not valid or is not supported by this function"
    );

  // Extract the RGB color elements as a single string
  // The individual color elements are separated by commas
  return (hexToRGBMapping?.[hexCode]).slice(4, -1);
};

/**
 * Concatenates metadata properties into a single string with an ampersand as the delimiter
 * @param {Array} metadataPropertiesArr An array of metadata property strings
 * @returns {String} A string made up of combined metadata properties delimited by an ampersand
 */
const createCombinedTextDelimitedByAmpersand = function (
  metadataPropertiesArr
) {
  return metadataPropertiesArr.join(" & ");
};

/**
 * Concatenates metadata properties into a single string with a comma as the delimiter
 * @param {Array} metadataPropertiesArr An array of metadata property strings
 * @returns {String} A string made up of combined metadata properties delimited by a comma
 */
const createCombinedTextDelimitedByComma = function (metadataPropertiesArr) {
  return metadataPropertiesArr.join(", ");
};

/**
 * Create a partial string for a line chart or column chart title
 * @param {String} aggregationInterval The aggregation interval as a string, either "daily" or "monthly"
 * @param {String} aggregationType The aggregation type as a string, either "sum" or "average"
 * @returns {String} Partial string for chart title
 */
const createPartialTitleForLineOrColumnChart = function (
  aggregationInterval,
  aggregationType
) {
  // Case 1: No aggregation; return empty string
  if (!aggregationInterval && !aggregationType) return ``;

  // Case 2: Aggregation; capitalize the first characters
  return `${
    aggregationInterval.slice(0, 1).toUpperCase() + aggregationInterval.slice(1)
  } ${aggregationType.slice(0, 1).toUpperCase() + aggregationType.slice(1)}`;
};

/**
 * Create a full string for a line chart or column chart title
 * @param {Array} datastreamNamesArr An array of datastream names as strings
 * @param {String} aggregationInterval The aggregation interval as a string, either "daily" or "monthly"
 * @param {String} aggregationType The aggregation type as a string, either "sum" or "average"
 * @returns {String} Full string for chart title
 */
const createFullTitleForLineOrColumnChart = function (
  phenomenonNamesArr,
  aggregationInterval,
  aggregationType
) {
  // Case 1: No aggregation; create a comma separated string of phenomenon names
  if (!aggregationInterval && !aggregationType)
    return `${createPartialTitleForLineOrColumnChart(
      aggregationInterval,
      aggregationType
    )}${createCombinedTextDelimitedByComma(phenomenonNamesArr)}`;

  // Case 2: Aggregation
  return `${createPartialTitleForLineOrColumnChart(
    aggregationInterval,
    aggregationType
  )} ${phenomenonNamesArr[0]}`;
};

/**
 * Creates a date string that is used in a shared tooltip for a line or column chart
 * @param {Number} pointXAxisValue The x-axis value (Unix timestamp) which is common for a set of data points
 * @param {String} aggregationInterval The aggregation interval as a string, either "daily" or "monthly"
 * @returns {String} A calendar date or calendar month string that is common for a set of data points
 */
const createTooltipDateString = function (
  pointXAxisValue,
  aggregationInterval
) {
  if (aggregationInterval === undefined || aggregationInterval === "daily")
    // When `aggregationInterval === undefined`, assume that we are displaying raw observations
    return `${Highcharts.dateFormat("%A, %b %e, %Y", pointXAxisValue)}`;
  else if (aggregationInterval === "monthly")
    return `${Highcharts.dateFormat("%b %Y", pointXAxisValue)}`;
};

/**
 * Extracts the sampling rate substring from a datastream name string
 * @param {Array} datastreamNamesArr An array of datastream name(s)
 * @returns {Array} An array containing the sampling rate substring(s)
 */
const extractSamplingRateFromDatastreamName = function (datastreamNamesArr) {
  // The sampling rate string is the last word in the Datastream name string
  return datastreamNamesArr.map((datastreamName) =>
    datastreamName.split(" ").pop()
  );
};

/**
 * Remove the transparency (alpha channel) from a color
 * @param {String} rgbaColor A color expressed in RGBA format
 * @returns {String} A color in RGB format
 */
const removeTransparencyFromColor = function (rgbaColor) {
  return `rgb(${rgbaColor.slice(5, -5)})`;
};

export {
  chartExportOptions,
  createCombinedTextDelimitedByAmpersand,
  createCombinedTextDelimitedByComma,
  createFullTitleForLineOrColumnChart,
  createTooltipDateString,
  convertHexColorToRGBColor,
  extractSamplingRateFromDatastreamName,
  removeTransparencyFromColor,
};
