import React, {Component} from 'react';

import {azint_unit, DefaultService, plot_type, plot_unit_x, plots} from "../openapi";
import MultiLinePlotWrapper from "./MultiLinePlotWrapper";

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

type MyState = {
    plots : plots,
    connection_error: boolean
}

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 | JSX.Element {
    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 | JSX.Element {
    switch (plot) {
        case plot_type.IMAGE_COLLECTION_EFFICIENCY:
            return "Efficiency";
        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 "Spot count";
        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.INDEXING_TIME:
        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]";
        default:
            return "?";
    }
}

class DataProcessingPlot extends Component<MyProps, MyState> {
    interval: ReturnType<typeof setInterval> | undefined;

    state: MyState = {
        plots: {
            plot : [
                {
                    x: [0, 100, 200, 300, 400, 500],
                    y: [0.1, 0.3, 0.5, 0.2, 0.0, 0.1],
                    title: "Example"
                }
            ],
            unit_x: plot_unit_x.IMAGE_NUMBER
        },
        connection_error: true
    }

    getValues() {
        DefaultService.getPreviewPlot(this.props.type, this.props.binning, true,  undefined,
            this.props.angle, this.props.azint)
            .then(data => this.setState({plots: data, connection_error: false}))
            .catch(error => {
                this.setState({connection_error: true});
            });
    }

    componentDidMount() {
        this.getValues();
        this.interval = setInterval(() => this.getValues(), 1000);
    }

    componentWillUnmount() {
        clearInterval(this.interval);
    }

    render() {
        if (this.state.connection_error
            || (this.state.plots === undefined)
            || (this.state.plots.plot === null)
            || (this.state.plots.plot.length === 0))
            return <div>No plots available</div>;

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

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

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

export default DataProcessingPlot;
