Source: utils/template/functions/custom/marehubOverview.js

import Plotly from 'plotly.js-dist';
import { displayMessage } from '../../../utils.js';
import { PlotlyVefPlot } from '../../../../plot/templates/PlotlyVefPlot.js';

// static plot container
let vefPlotly = null;
let plotInterval = null;
let plotTimeout = null;


function clearTimers() {
    if (plotInterval) clearInterval(plotInterval);
    if (plotTimeout) clearTimeout(plotTimeout);
    plotInterval = null;
    plotTimeout = null;
}


function plotInSidebar(data, layout) {
    const target = document.createElement("div");
    target.style.width = "100%";
    target.classList.add("vef-plot");

    clearTimers();

    const createPlot = () => {
        clearTimers();
        if (vefPlotly) Plotly.purge(vefPlotly.graphDiv);
        vefPlotly = new PlotlyVefPlot(target, data, layout);
        Plotly.newPlot(vefPlotly.graphDiv, vefPlotly.data, vefPlotly.layout, vefPlotly.config);
        vefPlotly.extensions.apply({ 'redirectNotification': { 'callback': displayMessage } });
    };

    // only init plot if the target is visible in DOM (offsetParent == null if not displayed)
    // use timeout to push to end of eventloop. If not in DOM check repeatedly
    plotTimeout = setTimeout(() => {
        if (target.offsetParent) {
            createPlot()
        } else {
            plotInterval = setInterval(() => {
                if (target.offsetParent) createPlot();
            }, 700);
        }
    }, 50);

    return target;
}


export function getDateTimeFromWMSResponse(str) {
    if (!str) return str
    //'{"2020-02-20 00:00:00","2020-02-20 23:59:00"}' -> ISO format only in future
    return str.match(/\d{4}-\d{2}-\d{2}[\sT]\d{2}:\d{2}:\d{2}(?:\.\d+)?/g)
}


export function getNumbersFromWMSResponse(arg) {
    if (!arg) return arg
    //"{27.009,27.008,27.007,27.000,27.001,26.997}"
    const sqlString = arg.toString();
    const stringNumbers = sqlString.match(/(?:[+-])?\d+(?:\.\d+)?/g);
    const floatNumbers = stringNumbers.map(item => parseFloat(item));
    return floatNumbers
}

/**
 * Creates an elementary plot 
 * 
 * 
 * @param {*} valueX 
 * @param {*} valueY 
 * @param {string} labelX 
 * @param {string} labelY 
 * @returns {HTMLElement} span placeholder
 */
export function plot(valueX, valueY, labelX, labelY) {
    if (valueX == null || valueY == null)
        return undefined

    const data = [{ x: valueX, y: valueY }];
    const layout = {
        xaxis: { title: { text: labelX } },
        yaxis: { title: { text: labelY } }
    };

    return plotInSidebar(data, layout);
}

/**
 * Creates an overview plot for the measurements layers
 * 
 * @param {object} properties
 * @param {object} data response
 * @returns {string} span placeholder
 * 
 */
export function marehubOverviewPlot(properties) {
    if (properties.ov_type && (properties.value_cnt > 1)) {
        const times = getDateTimeFromWMSResponse(properties.times);
        const depths = getNumbersFromWMSResponse(properties.depths);
        const values = getNumbersFromWMSResponse(properties.values);

        if (values) {
            // create regular plots
            switch (properties.ov_type) {
                case "depth profile, stationary":
                    if (depths && (depths.length > 0)) {
                        const data = [{ x: values, y: depths }];

                        const labelX = properties.parameter_name + ((properties.parameter_unit) ? ` [${properties.parameter_unit}]` : '');
                        const labelY = (properties.depth_type || "depth") + " [m]";
                        const layout = {
                            hovermode: "y",
                            xaxis: { title: { text: labelX } },
                            yaxis: { title: { text: labelY }, autorange: "reversed" }
                        }

                        return plotInSidebar(data, layout);
                    }
                    break;
                case "time series, stationary":
                case "time series, moving":
                    if (times && (times.length > 0)) {
                        const data = [{ x: times, y: values }];

                        const labelX = "Time of Day";
                        const labelY = properties.parameter_name + ((properties.parameter_unit) ? ` [${properties.parameter_unit}]` : '');
                        const layout = {
                            xaxis: { title: { text: labelX } },
                            yaxis: { title: { text: labelY } }
                        }

                        return plotInSidebar(data, layout);
                    }
                    break;
            }
        } else {
            // special case for current
            const values_vc = getNumbersFromWMSResponse(properties.values_vc);
            const values_uc = getNumbersFromWMSResponse(properties.values_uc);

            if (!values_vc || !values_uc) return undefined;

            switch (properties.ov_type) {
                case "depth profile, stationary":
                    if (depths && (depths.length > 0)) {
                        const data = [
                            { x: values_vc, y: depths, name: "VC" },
                            { x: values_uc, y: depths, name: "UC" }
                        ]

                        const labelX = "Current Velocity" + ((properties.parameter_unit) ? ` [${properties.parameter_unit}]` : '');
                        const labelY = (properties.depth_type || "depth") + " [m]";
                        const layout = {
                            hovermode: "y",
                            xaxis: { title: { text: labelX } },
                            yaxis: { title: { text: labelY }, autorange: "reversed" }
                        }

                        return plotInSidebar(data, layout);
                    }
                    break;
                case "time series, stationary":
                case "time series, moving":
                    if (times && (times.length > 0)) {
                        const data = [
                            { y: values_vc, x: times, name: "VC" },
                            { y: values_uc, x: times, name: "UC" }
                        ]

                        const labelX = "Time of Day";
                        const labelY = "Current Velocity" + ((properties.parameter_unit) ? ` [${properties.parameter_unit}]` : '');
                        const layout = {
                            xaxis: { title: { text: labelX } },
                            yaxis: { title: { text: labelY } }
                        }

                        return plotInSidebar(data, layout);
                    }
                    break;
            }
        }

    }

    return undefined;
}

/**
 * Prints the value with unit if only one value exists
 * 
 * @param {*} properties 
 * @param {*} column 
 * @param {*} unit 
 * @returns {string} value
 */
export function getMarehubOverviewValue(properties, column, unit) {
    column = column || "values";
    unit = unit || properties.parameter_unit;

    if (properties.value_cnt == 1) {
        const values = getNumbersFromWMSResponse(properties[column]);
        if (values?.length == 1) {
            let value = values[0];
            if (unit) value += " " + unit;
            return value
        }
    }

    return undefined;
}