Source: timeseriesPlot.js

// Utility functions
import { pm25ToYMax, pm25_AQILines } from "./plot-utils.js";
import { requireLuxonDateTimeArray } from "./helpers.js";

/**
 * Returns a timeseriesPlot chart configuration.
 * @param {Object} data The data required to create the chart.
 * @param {DateTime[]} data.datetime - Array of Luxon DateTime objects in UTC.
 * @param {number[]} data.pm25 - PM2.5 values aligned with datetime.
 * @param {number[]} data.nowcast - NowCast values aligned with datetime.
 * @param {string} data.locationName - Site or label name.
 * @param {string} data.timezone - IANA timezone string for x-axis display.
 * @param {string} [data.title] - Optional custom chart title.
 * @returns {Object} Highcharts chart config.
 */
export function timeseriesPlotConfig(data) {
  requireLuxonDateTimeArray(data.datetime, "datetime");

  const startTime = data.datetime[0]; // assumed to be Luxon DateTime
  const ymin = 0;
  const ymax = pm25ToYMax(Math.max(...data.pm25));

  const title = data.title ?? data.locationName;

  return {
    accessibility: { enabled: false },
    chart: {
      animation: false,
      plotBorderColor: "#ddd",
      plotBorderWidth: 1,
    },
    plotOptions: {
      series: { animation: false },
    },
    tooltip: { shared: true },
    title: { text: title },
    time: {
      timezone: data.timezone,
      useUTC: false,
    },
    xAxis: {
      type: "datetime",
      gridLineColor: "#ddd",
      gridLineDashStyle: "Dash",
      gridLineWidth: 1,
      minorTicks: true,
      minorTickInterval: 3 * 3600 * 1000, // every 3 hours
      minorGridLineColor: "#eee",
      minorGridLineDashStyle: "Dot",
      minorGridLineWidth: 1,
    },
    yAxis: {
      min: ymin,
      max: ymax,
      gridLineColor: "#ddd",
      gridLineDashStyle: "Dash",
      gridLineWidth: 1,
      title: {
        text: "PM2.5 (\u00b5g/m\u00b3)",
      },
      plotLines: pm25_AQILines(2),
    },
    legend: {
      enabled: true,
      verticalAlign: "top",
    },
    series: [
      {
        name: "Hourly PM2.5",
        type: "line",
        pointInterval: 3600 * 1000,
        pointStart: startTime.toMillis(),
        data: data.pm25,
        lineWidth: 0,
        color: "transparent",
        marker: {
          enabled: true,
          radius: 3,
          symbol: "circle",
          fillColor: "#bbbbbb",
        },
      },
      {
        name: "Nowcast",
        type: "line",
        lineWidth: 2,
        pointInterval: 3600 * 1000,
        pointStart: startTime.toMillis(),
        data: data.nowcast,
        color: "#000",
        marker: { radius: 1, symbol: "square", fillColor: "transparent" },
      },
    ],
  };
}

/**
 * Returns a simplified version of the timeseries plot configuration.
 * This small variant disables legends and axis labels for use in
 * small-multiples or compact visual displays.
 *
 * @param {Object} data The data required to create the chart.
 * @param {DateTime[]} data.datetime - Array of Luxon DateTime objects in UTC.
 * @param {number[]} data.pm25 - PM2.5 values aligned with datetime.
 * @param {number[]} data.nowcast - NowCast values aligned with datetime.
 * @param {string} data.locationName - Site or label name.
 * @param {string} data.timezone - IANA timezone string for x-axis display.
 * @param {string} [data.title] - Optional custom chart title.
 * @returns {Object} Highcharts chart config.
 */
export function small_timeseriesPlotConfig(data) {
  requireLuxonDateTimeArray(data.datetime, "datetime");

  const startTime = data.datetime[0];
  const ymin = 0;
  const ymax = pm25ToYMax(Math.max(...data.pm25));

  const title = data.title ?? data.locationName;

  return {
    accessibility: { enabled: false },
    chart: {
      animation: false,
    },
    plotOptions: {
      series: { animation: false },
      scatter: {
        animation: false,
        marker: { radius: 2, symbol: "circle", fillColor: "#bbbbbb" },
      },
      line: {
        animation: false,
        color: "#000",
        lineWidth: 0.5,
        marker: { enabled: false },
      },
    },
    tooltip: { shared: true },
    title: {
      text: title,
      style: { color: "#333333", fontSize: "12px" },
    },
    time: {
      timezone: data.timezone,
      useUTC: false,
    },
    xAxis: {
      type: "datetime",
      visible: false,
    },
    yAxis: {
      min: ymin,
      max: ymax,
      title: { text: "" },
      plotLines: pm25_AQILines(1),
    },
    legend: { enabled: false },
    series: [
      {
        name: "Hourly PM2.5",
        type: "line",
        pointInterval: 3600 * 1000,
        pointStart: startTime.toMillis(),
        data: data.pm25,
        lineWidth: 0,
        color: "transparent",
        marker: {
          enabled: true,
          radius: 2,
          symbol: "circle",
          fillColor: "#bbbbbb",
        },
      },
      {
        name: "Nowcast",
        type: "line",
        lineWidth: 1,
        pointInterval: 3600 * 1000,
        pointStart: startTime.toMillis(),
        data: data.nowcast,
      },
    ],
  };
}