import {ReactNode} from 'react';

import {useQuery} from "@tanstack/react-query";
import {azint_unit, plot_type, plot_unit_x} from "../client";
import {getPreviewPlotOptions} from "../client/@tanstack/react-query.gen";
import MultiLinePlotWrapper from "./MultiLinePlotWrapper";

type MyProps = {
    type: plot_type;
    binning: number;
    angle: boolean;
    azint: azint_unit;
};

type PlotlyPlot = {
    x: number[],
    y: (number | null)[],
    z?: (number | null)[],
    type: string,
    mode?: string,
    name?: string,
    colorscale?: string
}

type PlotlyData = PlotlyPlot[]

function AxisTypeX(unit: plot_unit_x) : string | ReactNode {
    if (unit == plot_unit_x.Q_RECIP_A)
        return "Q [&#8491;<sup>-1</sup>]";
    else if (unit == plot_unit_x.ANGLE_DEG)
        return "Rotation angle [deg]";
    else if (unit == plot_unit_x.ADU)
        return "ADU";
    else if (unit == plot_unit_x.D_A)
        return "d [&#8491;]";
    else if (unit == plot_unit_x.GRID_UM)
        return "Grid position [µm]";
    else
        return "Image number";
}

function AxisTypeY(plot: plot_type) : string | ReactNode {
    switch (plot) {
        case plot_type.IMAGE_COLLECTION_EFFICIENCY:
            return "Efficiency";
        case plot_type.INDEXING_LATTICE_COUNT:
        case plot_type.INTEGRATED_REFLECTIONS:
        case plot_type.SPOT_COUNT:
        case plot_type.SPOT_COUNT_LOW_RES:
        case plot_type.SPOT_COUNT_INDEXED:
        case plot_type.SPOT_COUNT_ICE:
            return "Count";
        case plot_type.ICE_RING_SCORE:
            return "Ratio";
        case plot_type.AZINT:
        case plot_type.AZINT_1D:
        case plot_type.BKG_ESTIMATE:
            return "Arbitrary units";
        case plot_type.ROI_MAX_COUNT:
        case plot_type.ROI_SUM:
        case plot_type.ROI_MEAN:
            return "Photon count";
        case plot_type.INDEXING_RATE:
            return "Indexing rate";
        case plot_type.ERROR_PIXELS:
        case plot_type.STRONG_PIXELS:
            return "Pixel count";
        case plot_type.RECEIVER_DELAY:
            return "Delay";
        case plot_type.RECEIVER_FREE_SEND_BUF:
            return "Free buffers";
        case plot_type.INDEXING_UNIT_CELL_LENGTH:
            return "Length [&#8491;]";
        case plot_type.RESOLUTION_ESTIMATE:
            return "Resolution [&#8491;]";
        case plot_type.INDEXING_UNIT_CELL_ANGLE:
            return "Angle [deg]";
        case plot_type.MAX_PIXEL_VALUE:
            return "Max pixel value";
        case plot_type.ROI_WEIGHTED_X:
        case plot_type.ROI_WEIGHTED_Y:
            return "Position [pixel]";
        case plot_type.PROCESSING_TIME:
            return "Time [s]";
        case plot_type.PROFILE_RADIUS:
            return "Profile radius [&#8491;<sup>-1</sup>]";
        case plot_type.B_FACTOR:
            return "B-factor [&#8491;<sup>2</sup>]";
        case plot_type.BEAM_CENTER_X:
        case plot_type.BEAM_CENTER_Y:
            return "Beam center [pixel]";
        case plot_type.COMPRESSION_RATIO:
            return "Compression ratio";
        default:
            return "?";
    }
}

function DataProcessingPlot({type, binning, angle, azint}: MyProps) {
    const {data: plots, isError} = useQuery({
        ...getPreviewPlotOptions({ query: { type, binning, experimental_coord: angle, azint_unit: azint } }),
        refetchInterval: 1000,
    });

    if (isError
        || (plots === undefined)
        || (plots.plot === null)
        || (plots.plot.length === 0))
        return <div>No plots available</div>;

    let data: PlotlyData = [];
    if ((plots.plot[0].z !== undefined)
        && (plots.plot[0].z.length > 0)) {

        data.push({
            x: plots.plot[0].x,
            y: plots.plot[0].y,
            z: plots.plot[0].z,
            type: "heatmap",
            colorscale: "Viridis"
        })
        return <MultiLinePlotWrapper xaxis={AxisTypeX(plots.unit_x)}
                                     yaxis={AxisTypeY(type)}
                                     data={data}
                                     grid_scan={true}
                                     range_x={plots.size_x}
                                     range_y={plots.size_y}/>

    } else {
        plots.plot.map(d =>
            data.push({
                x: d.x,
                y: d.y,
                type: "scatter",
                mode: "line",
                name: d.title
            }));
        return <MultiLinePlotWrapper xaxis={AxisTypeX(plots.unit_x)}
                                     yaxis={AxisTypeY(type)}
                                     data={data}
                                     grid_scan={false}/>
    }
}

export default DataProcessingPlot;
