"use strict";

import { drawLineChartHighcharts } from "./chartLine.mjs";

import {
  formatSensorThingsApiResponseForHeatMap,
  drawHeatMapHighcharts,
} from "./chartHeatmap.mjs";

import {
  formatSensorThingsApiResponseForScatterPlot,
  drawScatterPlotHighcharts,
} from "./chartScatterPlot.mjs";

import {
  formatAggregationResultForColumnChart,
  drawColumnChartHighcharts,
} from "./chartColumn.mjs";

import { extractUniqueCalendarMonthsFromCalendarDates } from "./aggregateHelpers.mjs";

import {
  calculateMinimumObservationValuesWithinInterval,
  calculateMaximumObservationValuesWithinInterval,
  calculateSumOfObservationValuesWithinInterval,
  calculateAverageOfObservationValuesWithinInterval,
} from "./aggregate.mjs";

import { extractPropertiesFromFormattedDatastreamMetadata } from "./fetchedDataProcessing.mjs";

/**
 * Draw a heatmap based on the selected options from a drop-down list
 *
 * @param {Array} observationsComboNestedArr An array that contains non-computed (raw) observations and computed (temperature difference, dT) observations
 * @param {Object} extractedFormattedDatastreamProperties An object that contains array(s) of formatted Datastream properties
 * @returns {undefined} undefined
 */
const drawHeatmapBasedOnSelectedOptions = function (
  observationsComboNestedArr,
  extractedFormattedDatastreamProperties
) {
  // Create formatted array(s) for observations
  const formattedObservationsHeatMapNestedArr = observationsComboNestedArr.map(
    (observationsArr) =>
      formatSensorThingsApiResponseForHeatMap(observationsArr)
  );

  // Note: The resulting array is nested and is not suitable for heatmap,
  // extract the nested array
  const [formattedObservationsHeatMapArr] =
    formattedObservationsHeatMapNestedArr;

  drawHeatMapHighcharts(
    formattedObservationsHeatMapArr,
    extractedFormattedDatastreamProperties
  );
};

/**
 * Draw a scatter plot based on the selected options from a drop-down list
 *
 * @param {Array} observationsComboNestedArr An array that contains non-computed (raw) observations and computed (temperature difference, dT) observations
 * @param {Object} extractedFormattedDatastreamProperties An object that contains array(s) of formatted Datastream properties
 * @returns {undefined} undefined
 */
const drawScatterPlotFromChartSelection = function (
  observationsComboNestedArr,
  extractedFormattedDatastreamProperties
) {
  // Extract values for x-axis and y-axis
  // x-axis values are first element of nested observations array
  const [obsXAxisArr] = observationsComboNestedArr.slice(0, 1);
  // y-axis values are rest of elements of nested observations array
  const obsYAxisNestedArr = observationsComboNestedArr.slice(1);

  // Create formatted array(s) for observations
  const formattedObservationsScatterPlotArr = obsYAxisNestedArr.map(
    (obsYAxisArr) =>
      formatSensorThingsApiResponseForScatterPlot(obsXAxisArr, obsYAxisArr)
  );

  drawScatterPlotHighcharts(
    formattedObservationsScatterPlotArr,
    extractedFormattedDatastreamProperties
  );
};

/**
 * Calculate the daily sum of observations and format these aggregated observations
 *
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {Array} An array whose first element is the formatted aggregated (daily sum) observations. The second element is an object made up of extracted & formatted datastream properties
 */
const calculateAndFormatDailySumObservations = function (
  uniqueCalendarDatesNestedArr,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  formattedMetadataNestedArr
) {
  // Calculate sum of values of observations - daily
  const observationsSumDailyNestedArr =
    calculateSumOfObservationValuesWithinInterval(
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      uniqueCalendarDatesNestedArr,
      "daily"
    );

  // Format the observations - sum / daily
  const formattedObservationsSumDailyNestedArr =
    observationsSumDailyNestedArr.map((obsSumDailyArr, i) =>
      formatAggregationResultForColumnChart(
        uniqueCalendarDatesNestedArr[i],
        obsSumDailyArr
      )
    );

  // Extract the formatted metadata properties
  const extractedFormattedDatastreamProperties =
    extractPropertiesFromFormattedDatastreamMetadata(
      formattedMetadataNestedArr,
      true,
      "daily",
      "sum"
    );

  return [
    formattedObservationsSumDailyNestedArr,
    extractedFormattedDatastreamProperties,
  ];
};

/**
 * Calculate the monthly sum of observations and format these aggregated observations
 *
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {Array} An array whose first element is the formatted aggregated (monthly sum) observations. The second element is an object made up of extracted & formatted datastream properties
 */
const calculateAndFormatMonthlySumObservations = function (
  uniqueCalendarDatesNestedArr,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  formattedMetadataNestedArr
) {
  // Unique calendar months
  const uniqueCalendarMonthsNestedArr = uniqueCalendarDatesNestedArr.map(
    (uniqueCalendarDatesArr) =>
      extractUniqueCalendarMonthsFromCalendarDates(uniqueCalendarDatesArr)
  );

  // Calculate sum of values of observations - monthly
  const observationsSumMonthlyNestedArr =
    calculateSumOfObservationValuesWithinInterval(
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      uniqueCalendarMonthsNestedArr,
      "monthly"
    );

  // Format the observations - sum / monthly
  const formattedObservationsSumMonthlyNestedArr =
    observationsSumMonthlyNestedArr.map((obsSumMonthlyArr, i) =>
      formatAggregationResultForColumnChart(
        uniqueCalendarMonthsNestedArr[i],
        obsSumMonthlyArr
      )
    );

  // Extract the formatted metadata properties
  const extractedFormattedDatastreamProperties =
    extractPropertiesFromFormattedDatastreamMetadata(
      formattedMetadataNestedArr,
      true,
      "monthly",
      "sum"
    );

  return [
    formattedObservationsSumMonthlyNestedArr,
    extractedFormattedDatastreamProperties,
  ];
};

/**
 * Calculate the daily maximum of observations and format these aggregated observations
 *
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {Array} An array whose first element is the formatted aggregated (daily maximum) observations. The second element is an object made up of extracted & formatted datastream properties
 */
const calculateAndFormatDailyMaximumObservations = function (
  uniqueCalendarDatesNestedArr,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  formattedMetadataNestedArr
) {
  // Calculate minimum of values of observations - daily
  const observationsMaximumDailyNestedArr =
    calculateMaximumObservationValuesWithinInterval(
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      uniqueCalendarDatesNestedArr,
      "daily"
    );

  // Format the observations - min / daily
  const formattedObservationsMaximumDailyNestedArr =
    observationsMaximumDailyNestedArr.map((obsMinDailyArr, i) =>
      formatAggregationResultForColumnChart(
        uniqueCalendarDatesNestedArr[i],
        obsMinDailyArr
      )
    );

  // Extract the formatted metadata properties
  const extractedFormattedDatastreamProperties =
    extractPropertiesFromFormattedDatastreamMetadata(
      formattedMetadataNestedArr,
      true,
      "daily",
      "maximum"
    );

  return [
    formattedObservationsMaximumDailyNestedArr,
    extractedFormattedDatastreamProperties,
  ];
};

/**
 * Calculate the monthly maximum of observations and format these aggregated observations
 *
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {Array} An array whose first element is the formatted aggregated (monthly maximum) observations. The second element is an object made up of extracted & formatted datastream properties
 */
const calculateAndFormatMonthlyMaximumObservations = function (
  uniqueCalendarDatesNestedArr,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  formattedMetadataNestedArr
) {
  // Unique calendar months
  const uniqueCalendarMonthsNestedArr = uniqueCalendarDatesNestedArr.map(
    (uniqueCalendarDatesArr) =>
      extractUniqueCalendarMonthsFromCalendarDates(uniqueCalendarDatesArr)
  );

  // Calculate minimum of values of observations - monthly
  const observationsMaximumMonthlyNestedArr =
    calculateMaximumObservationValuesWithinInterval(
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      uniqueCalendarMonthsNestedArr,
      "monthly"
    );

  // Format the observations - max / monthly
  const formattedObservationsMaximumMonthlyNestedArr =
    observationsMaximumMonthlyNestedArr.map((obsMaxMonthlyArr, i) =>
      formatAggregationResultForColumnChart(
        uniqueCalendarMonthsNestedArr[i],
        obsMaxMonthlyArr
      )
    );

  // Extract the formatted metadata properties
  const extractedFormattedDatastreamProperties =
    extractPropertiesFromFormattedDatastreamMetadata(
      formattedMetadataNestedArr,
      true,
      "monthly",
      "maximum"
    );

  return [
    formattedObservationsMaximumMonthlyNestedArr,
    extractedFormattedDatastreamProperties,
  ];
};

/**
 * Calculate the daily minimum of observations and format these aggregated observations
 *
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {Array} An array whose first element is the formatted aggregated (daily minimum) observations. The second element is an object made up of extracted & formatted datastream properties
 */
const calculateAndFormatDailyMinimumObservations = function (
  uniqueCalendarDatesNestedArr,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  formattedMetadataNestedArr
) {
  // Calculate minimum of values of observations - daily
  const observationsMinimumDailyNestedArr =
    calculateMinimumObservationValuesWithinInterval(
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      uniqueCalendarDatesNestedArr,
      "daily"
    );

  // Format the observations - min / daily
  const formattedObservationsMinimumDailyNestedArr =
    observationsMinimumDailyNestedArr.map((obsMinDailyArr, i) =>
      formatAggregationResultForColumnChart(
        uniqueCalendarDatesNestedArr[i],
        obsMinDailyArr
      )
    );

  // Extract the formatted metadata properties
  const extractedFormattedDatastreamProperties =
    extractPropertiesFromFormattedDatastreamMetadata(
      formattedMetadataNestedArr,
      true,
      "daily",
      "minimum"
    );

  return [
    formattedObservationsMinimumDailyNestedArr,
    extractedFormattedDatastreamProperties,
  ];
};

/**
 * Calculate the monthly minimum of observations and format these aggregated observations
 *
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {Array} An array whose first element is the formatted aggregated (monthly minimum) observations. The second element is an object made up of extracted & formatted datastream properties
 */
const calculateAndFormatMonthlyMinimumObservations = function (
  uniqueCalendarDatesNestedArr,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  formattedMetadataNestedArr
) {
  // Unique calendar months
  const uniqueCalendarMonthsNestedArr = uniqueCalendarDatesNestedArr.map(
    (uniqueCalendarDatesArr) =>
      extractUniqueCalendarMonthsFromCalendarDates(uniqueCalendarDatesArr)
  );

  // Calculate minimum of values of observations - monthly
  const observationsMinimumMonthlyNestedArr =
    calculateMinimumObservationValuesWithinInterval(
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      uniqueCalendarMonthsNestedArr,
      "monthly"
    );

  // Format the observations - min / monthly
  const formattedObservationsMinimumMonthlyNestedArr =
    observationsMinimumMonthlyNestedArr.map((obsMinMonthlyArr, i) =>
      formatAggregationResultForColumnChart(
        uniqueCalendarMonthsNestedArr[i],
        obsMinMonthlyArr
      )
    );

  // Extract the formatted metadata properties
  const extractedFormattedDatastreamProperties =
    extractPropertiesFromFormattedDatastreamMetadata(
      formattedMetadataNestedArr,
      true,
      "monthly",
      "minimum"
    );

  return [
    formattedObservationsMinimumMonthlyNestedArr,
    extractedFormattedDatastreamProperties,
  ];
};

/**
 * Calculate the daily average of observations and format these aggregated observations
 *
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {Array} An array whose first element is the formatted aggregated (daily average) observations. The second element is an object made up of extracted & formatted datastream properties
 */
const calculateAndFormatDailyAverageObservations = function (
  uniqueCalendarDatesNestedArr,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  formattedMetadataNestedArr
) {
  // Calculate average of values of observations - daily
  const observationsAverageDailyNestedArr =
    calculateAverageOfObservationValuesWithinInterval(
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      uniqueCalendarDatesNestedArr,
      "daily"
    );

  // Format the observations - average / daily
  const formattedObservationsAverageDailyNestedArr =
    observationsAverageDailyNestedArr.map((obsAverageDailyArr, i) =>
      formatAggregationResultForColumnChart(
        uniqueCalendarDatesNestedArr[i],
        obsAverageDailyArr
      )
    );

  // Extract the formatted metadata properties
  const extractedFormattedDatastreamProperties =
    extractPropertiesFromFormattedDatastreamMetadata(
      formattedMetadataNestedArr,
      true,
      "daily",
      "average"
    );

  return [
    formattedObservationsAverageDailyNestedArr,
    extractedFormattedDatastreamProperties,
  ];
};

/**
 * Calculate the monthly average of observations and format these aggregated observations
 *
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {Array} An array whose first element is the formatted aggregated (monthly average) observations. The second element is an object made up of extracted & formatted datastream properties
 */
const calculateAndFormatMonthlyAverageObservations = function (
  uniqueCalendarDatesNestedArr,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  formattedMetadataNestedArr
) {
  // Unique calendar months
  const uniqueCalendarMonthsNestedArr = uniqueCalendarDatesNestedArr.map(
    (uniqueCalendarDatesArr) =>
      extractUniqueCalendarMonthsFromCalendarDates(uniqueCalendarDatesArr)
  );

  // Calculate average of values of observations - monthly
  const observationsAverageMonthlyNestedArr =
    calculateAverageOfObservationValuesWithinInterval(
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      uniqueCalendarMonthsNestedArr,
      "monthly"
    );

  // Format the observations - average / monthly
  const formattedObservationsAverageMonthlyNestedArr =
    observationsAverageMonthlyNestedArr.map((obsAverageMonthlyArr, i) =>
      formatAggregationResultForColumnChart(
        uniqueCalendarMonthsNestedArr[i],
        obsAverageMonthlyArr
      )
    );

  // Extract the formatted metadata properties
  const extractedFormattedDatastreamProperties =
    extractPropertiesFromFormattedDatastreamMetadata(
      formattedMetadataNestedArr,
      true,
      "monthly",
      "average"
    );

  return [
    formattedObservationsAverageMonthlyNestedArr,
    extractedFormattedDatastreamProperties,
  ];
};

/**
 * Draw a line chart based on the selected aggregation options from a drop-down list
 *
 * @param {String} selectedAggregationType A string representing the selected aggregation type. The currently supported strings include `Sum`, `Maximum`, `Minimum` and `Average`
 * @param {String} selectedAggregationDuration A string representing the selected aggregation duration. The currently supported strings include `Daily` and `Monthly`
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {undefined} undefined
 */
const drawLineChartBasedOnSelectedAggregationOptions = function (
  selectedAggregationType,
  selectedAggregationDuration,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  uniqueCalendarDatesNestedArr,
  formattedMetadataNestedArr
) {
  if (
    selectedAggregationType === "Sum" &&
    selectedAggregationDuration === "Daily"
  ) {
    // Formatted observations and metadata for chart - daily / sum
    const [
      formattedObservationsSumDailyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatDailySumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawLineChartHighcharts(
      formattedObservationsSumDailyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationType === "Sum" &&
    selectedAggregationDuration === "Monthly"
  ) {
    // Formatted observations and metadata for chart - monthly / sum
    const [
      formattedObservationsSumMonthlyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatMonthlySumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawLineChartHighcharts(
      formattedObservationsSumMonthlyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationType === "Maximum" &&
    selectedAggregationDuration === "Daily"
  ) {
    // Formatted observations and metadata for chart - daily / maximum
    const [
      formattedObservationsMaximumDailyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatDailyMaximumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawLineChartHighcharts(
      formattedObservationsMaximumDailyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationType === "Maximum" &&
    selectedAggregationDuration === "Monthly"
  ) {
    // Formatted observations and metadata for chart - monthly / maximum
    const [
      formattedObservationsMaximumMonthlyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatMonthlyMaximumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawLineChartHighcharts(
      formattedObservationsMaximumMonthlyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationType === "Minimum" &&
    selectedAggregationDuration === "Daily"
  ) {
    // Formatted observations and metadata for chart - daily / minimum
    const [
      formattedObservationsMinimumDailyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatDailyMinimumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawLineChartHighcharts(
      formattedObservationsMinimumDailyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationType === "Minimum" &&
    selectedAggregationDuration === "Monthly"
  ) {
    // Formatted observations and metadata for chart - monthly / minimum
    const [
      formattedObservationsMinimumMonthlyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatMonthlyMinimumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawLineChartHighcharts(
      formattedObservationsMinimumMonthlyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationType === "Average" &&
    selectedAggregationDuration === "Daily"
  ) {
    // Formatted observations and metadata for chart - daily / average
    const [
      formattedObservationsAverageDailyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatDailyAverageObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawLineChartHighcharts(
      formattedObservationsAverageDailyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationType === "Average" &&
    selectedAggregationDuration === "Monthly"
  ) {
    // Formatted observations and metadata for chart - monthly / average
    const [
      formattedObservationsAverageMonthlyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatMonthlyAverageObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawLineChartHighcharts(
      formattedObservationsAverageMonthlyNestedArr,
      extractedFormattedDatastreamProperties
    );
  }
};

/**
 * Draw a column chart based on the selected aggregation options from a drop-down list
 *
 * @param {String} selectedAggregationType A string representing the selected aggregation type. The currently supported strings include `Sum`, `Maximum`, `Minimum` and `Average`
 * @param {String} selectedAggregationDuration A string representing the selected aggregation duration. The currently supported strings include `Daily` and `Monthly`
 * @param {Array} observationsAggregationNestedArr An array made up of sub-array(s) of aggregated observations
 * @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
 * @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
 * @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
 * @returns {undefined} undefined
 */
const drawColumnChartBasedOnSelectedAggregationOptions = function (
  selectedAggregationTypeArr,
  selectedAggregationDuration,
  observationsAggregationNestedArr,
  selectedSamplingRateAbbrev,
  uniqueCalendarDatesNestedArr,
  formattedMetadataNestedArr
) {
  if (
    selectedAggregationTypeArr === "Sum" &&
    selectedAggregationDuration === "Daily"
  ) {
    // Formatted observations and metadata for chart - daily / sum
    const [
      formattedObservationsSumDailyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatDailySumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawColumnChartHighcharts(
      formattedObservationsSumDailyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationTypeArr === "Sum" &&
    selectedAggregationDuration === "Monthly"
  ) {
    // Formatted observations and metadata for chart - monthly / sum
    const [
      formattedObservationsSumMonthlyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatMonthlySumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawColumnChartHighcharts(
      formattedObservationsSumMonthlyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationTypeArr === "Maximum" &&
    selectedAggregationDuration === "Daily"
  ) {
    // Formatted observations and metadata for chart - daily / maximum
    const [
      formattedObservationsMaximumDailyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatDailyMaximumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawColumnChartHighcharts(
      formattedObservationsMaximumDailyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationTypeArr === "Maximum" &&
    selectedAggregationDuration === "Monthly"
  ) {
    // Formatted observations and metadata for chart - monthly / maximum
    const [
      formattedObservationsMaximumMonthlyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatMonthlyMaximumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawColumnChartHighcharts(
      formattedObservationsMaximumMonthlyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationTypeArr === "Minimum" &&
    selectedAggregationDuration === "Daily"
  ) {
    // Formatted observations and metadata for chart - daily / minimum
    const [
      formattedObservationsMinimumDailyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatDailyMinimumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawColumnChartHighcharts(
      formattedObservationsMinimumDailyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationTypeArr === "Minimum" &&
    selectedAggregationDuration === "Monthly"
  ) {
    // Formatted observations and metadata for chart - monthly / minimum
    const [
      formattedObservationsMinimumMonthlyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatMonthlyMinimumObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawColumnChartHighcharts(
      formattedObservationsMinimumMonthlyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationTypeArr === "Average" &&
    selectedAggregationDuration === "Daily"
  ) {
    // Formatted observations and metadata for chart - daily / average
    const [
      formattedObservationsAverageDailyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatDailyAverageObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawColumnChartHighcharts(
      formattedObservationsAverageDailyNestedArr,
      extractedFormattedDatastreamProperties
    );
  } else if (
    selectedAggregationTypeArr === "Average" &&
    selectedAggregationDuration === "Monthly"
  ) {
    // Formatted observations and metadata for chart - monthly / average
    const [
      formattedObservationsAverageMonthlyNestedArr,
      extractedFormattedDatastreamProperties,
    ] = calculateAndFormatMonthlyAverageObservations(
      uniqueCalendarDatesNestedArr,
      observationsAggregationNestedArr,
      selectedSamplingRateAbbrev,
      formattedMetadataNestedArr
    );

    drawColumnChartHighcharts(
      formattedObservationsAverageMonthlyNestedArr,
      extractedFormattedDatastreamProperties
    );
  }
};

export {
  drawHeatmapBasedOnSelectedOptions,
  drawScatterPlotFromChartSelection,
  drawLineChartBasedOnSelectedAggregationOptions,
  drawColumnChartBasedOnSelectedAggregationOptions,
};
