"use strict";

import {
  chartExportOptions,
  createFullTitleForLineOrColumnChart,
  createSubtitleForChart,
  createTooltipDateString,
} from "./chartHelpers.mjs";

/**
 * Format the response from SensorThings API to make it suitable for use in a line chart or column chart
 * @param {Array} obsArray Array of observations (timestamp + value) that is response from SensorThings API
 * @returns {Array} Array of formatted observations suitable for use in a line chart
 */
const formatSensorThingsApiResponseForLineOrColumnChart = function (obsArray) {
  if (!obsArray) return;

  return obsArray.map((result) => {
    const timestampObs = new Date(result[0].slice(0, -1)).getTime(); // slice() removes trailing "Z" character in timestamp
    const valueObs = result[1];
    return [timestampObs, valueObs];
  });
};

/**
 * Creates an options object for each series drawn in the line chart
 * @param {Array} formattedObsArraysForLineChart An array of formatted observation array(s) from one or more datastreams
 * @param {Array} buildingIdsPhenomenonNamesArr An array of string(s) made up of building ID(s) + phenomenon name(s)
 * @returns {Array} An array made up of series options object(s)
 */
const createSeriesOptionsForLineChart = function (
  formattedObsArraysForLineChart,
  buildingIdsPhenomenonNamesArr
) {
  // An array of colors, in hexadecimal format, provided by the global Highcharts object
  const seriesColors = Highcharts.getOptions().colors;

  // Create a copy of the colors array
  const seriesColorsArr = [...seriesColors];

  // Create an array of seriesOptions objects
  // Assumes that the observation array of arrays and building IDs + phenomenon names array are of equal length
  // Use one of the arrays for looping
  if (
    formattedObsArraysForLineChart.length !==
    buildingIdsPhenomenonNamesArr.length
  ) {
    throw new Error(
      "The observations array and phenomenon names array have different lengths"
    );
  } else {
    return formattedObsArraysForLineChart.map((formattedObsArray, i) => {
      return {
        name: `${buildingIdsPhenomenonNamesArr[i]}`,
        data: formattedObsArray,
        color: seriesColorsArr[i],
        turboThreshold: Number.MAX_VALUE, // #3404, remove after 4.0.5 release
      };
    });
  }
};

/**
 * Draw a line chart using Highcharts library
 * @param {Array} formattedObsArraysForLineChart An array made up of formatted observation array(s) suitable for use in a line chart. The observations may either be raw or aggregated
 * @param {Object} extractedFormattedDatastreamPropertiesArr An object that contains arrays of formatted Datastream properties
 * @returns {undefined} undefined
 */
const drawLineChartHighcharts = function (
  formattedObsArraysForLineChart,
  extractedFormattedDatastreamProperties
) {
  // Arrays of datastream properties
  let datastreamNamesArr,
    phenomenonNamesArr,
    buildingIdsPhenomenonNamesArr,
    unitOfMeasurementSymbolsArr,
    aggregationInterval,
    aggregationType;

  // Check whether the datastream properties are for aggregated observations
  if (extractedFormattedDatastreamProperties?.aggregationType === undefined) {
    // Case 1: No aggregation
    ({
      datastreamNamesArr,
      phenomenonNamesArr,
      buildingIdsPhenomenonNamesArr,
      unitOfMeasurementSymbolsArr,
    } = extractedFormattedDatastreamProperties);
  } else {
    // Case 2: Aggregation
    ({
      datastreamNamesArr,
      phenomenonNamesArr,
      buildingIdsPhenomenonNamesArr,
      unitOfMeasurementSymbolsArr,
      aggregationInterval,
      aggregationType,
    } = extractedFormattedDatastreamProperties);
  }

  // Chart title and subtitle text
  const textChartTitle = createFullTitleForLineOrColumnChart(
    phenomenonNamesArr,
    aggregationInterval,
    aggregationType
  );

  const textChartSubtitle = createSubtitleForChart(datastreamNamesArr);

  // Create the array of series options object(s)
  const seriesOptionsArr = createSeriesOptionsForLineChart(
    formattedObsArraysForLineChart,
    buildingIdsPhenomenonNamesArr,
    unitOfMeasurementSymbolsArr
  );

  Highcharts.stockChart("chart-line", {
    chart: {
      zoomType: "x",
    },

    rangeSelector: {
      selected: 5,
    },

    title: {
      text: textChartTitle,
      "align": "center",
    },

    subtitle: {
      text: textChartSubtitle,
      align: "center",
    },

    tooltip: {
      formatter() {
        // Our tooltip is split
        // this.x -- common for all points
        // this.points -- an array containing properties for each series
        return [
          `${createTooltipDateString(this.x, aggregationInterval)}`,
        ].concat(
          this.points
            ? this.points.map(
                (point, i) =>
                  `<span style="color:${point.color}">${
                    point.series.name
                  }</span>: <b>${point.y.toFixed(2)} ${
                    unitOfMeasurementSymbolsArr[i]
                  }</b>`
              )
            : []
        );
      },
    },

    exporting: chartExportOptions,

    series: seriesOptionsArr,
  });
};

export {
  formatSensorThingsApiResponseForLineOrColumnChart,
  drawLineChartHighcharts,
};
