import React from 'react';

import Paper from '@mui/material/Paper';
import {Stack, TextField, Radio, RadioGroup, FormControlLabel, FormControl, FormLabel, Checkbox} from "@mui/material";
import NumberTextField from "./NumberTextField";
import {dataset_settings, grid_scan, rotation_axis} from "../openapi";
import ButtonWithSnackbar from "./ButtonWithSnackbar";

type MyProps = {
    frame_time_us: number
};

type MyState = {
    s: dataset_settings,
    beam_x_pxl_err: boolean,
    beam_y_pxl_err: boolean,
    detector_distance_mm_err: boolean,
    incident_energy_kev_err: boolean,
    images_per_trigger_err: boolean,
    images_per_file_err: boolean,
    image_time_us_err: boolean,
    ntrigger_err: boolean,
    mode: 'still' | 'rotation' | 'grid',
    goniometer: rotation_axis,
    grid: grid_scan,
};

class DataCollection extends React.Component<MyProps, MyState> {
    state : MyState = {
        s : {
            beam_x_pxl: 0,
            beam_y_pxl: 0,
            detector_distance_mm: 100,
            incident_energy_keV: 12.398,
            images_per_trigger: 1,
            image_time_us: this.props.frame_time_us,
            ntrigger: 1,
            images_per_file: 1000
        },
        goniometer : {
          start: 0,
          step: 0.1,
          name: "omega",
            vector: [0,1,0]
        },
        grid: {
            n_fast: 10,
            step_x_um: 10.0,
            step_y_um: 10.0,
            vertical: false,
            snake: false
        },
        beam_x_pxl_err: false,
        beam_y_pxl_err: false,
        detector_distance_mm_err: false,
        incident_energy_kev_err: false,
        images_per_trigger_err: false,
        image_time_us_err: false,
        ntrigger_err: false,
        images_per_file_err: false,
        mode: 'still',
    }

    error() : boolean {
        return this.state.beam_x_pxl_err
            || this.state.beam_y_pxl_err
            || this.state.detector_distance_mm_err
            || this.state.incident_energy_kev_err
            || this.state.image_time_us_err
            || this.state.images_per_trigger_err
            || this.state.images_per_file_err
            || this.state.ntrigger_err;
    }

    getDatasetSettings = () => {
        let d = this.state.s;
        if (this.state.mode === 'rotation')
            d.goniometer = this.state.goniometer;
        else if (this.state.mode === 'grid')
            d.grid_scan = this.state.grid;
        return d;
    }

    render() {
        return <Paper style={{textAlign: 'center'}} sx={{ width: '100%'}}>
            <br/>
            <Stack spacing={5} sx={{
                justifyContent: "center",
                alignItems: "center",
            }}>
                <TextField label={"File prefix"}
                           variant="outlined"
                           onChange={
                               (event: React.ChangeEvent<HTMLInputElement>) => {
                                   this.setState(prevState => ({
                                       s: {...prevState.s, file_prefix: event.target.value}
                                   }));
                               }
                           }
                           value={this.state.s.file_prefix}
                           sx={{width:"90%"}}
                />
                <Stack direction="row" spacing={2} sx={{width: '90%'}}>
                    <NumberTextField
                        label={"Number of images per trigger"}
                        callback={(val: number, err: boolean) => {
                            this.setState(prevState => ({
                                    s: {...prevState.s, images_per_trigger: val},
                                    images_per_trigger_err: err
                                }
                            ));
                        }}
                        min={1}
                        default={this.state.s.images_per_trigger}
                    />
                    <NumberTextField
                        label={"Number of triggers"}
                        callback={(val: number, err: boolean) => {
                            this.setState(prevState => ({
                                    s: {...prevState.s, ntrigger: val},
                                    ntrigger_err: err
                                }
                            ));
                        }}
                        min={1}
                        default={this.state.s.ntrigger}
                    />
                    <NumberTextField
                        label={"Image time"}
                        callback={(val: number, err: boolean) => {
                            let image_time_us = Math.round(val * 1000.0);

                            this.setState(prevState => ({
                                    s: {...prevState.s,
                                        image_time_us: image_time_us
                                    },
                                    image_time_us_err: err
                                }
                            ));
                        }}
                        units={"ms"}
                        float={true}
                        min={0.01}
                        default={(this.state.s.image_time_us ?? 500) / 1000.0}
                    />

                    <NumberTextField
                        label={"Images per file"}
                        callback={(val: number, err: boolean) => {
                            this.setState(prevState => ({
                                    s: {...prevState.s,
                                        images_per_file: val
                                    },
                                    images_per_file_err: err
                                }
                            ));
                        }}
                        float={false}
                        min={1}
                        default={this.state.s.images_per_file}
                    />
                </Stack>
                <Stack direction="row" spacing={2} sx={{width: '90%'}}>
                    <NumberTextField
                        label={"Beam X [pxl]"}
                        callback={(val: number, err: boolean) => {
                            this.setState(prevState => ({
                                    s: {...prevState.s, beam_x_pxl: val},
                                    beam_x_pxl_err: err
                                }
                            ));
                        }}
                        units={"pxl"}
                        float={true}
                        default={this.state.s.beam_x_pxl}
                    />
                    <NumberTextField
                        label={"Beam Y"}
                        callback={(val: number, err: boolean) => {
                            this.setState(prevState => ({
                                    s: {...prevState.s, beam_y_pxl: val},
                                    beam_y_pxl_err: err
                                }
                            ));
                        }}
                        units={"pxl"}
                        float={true}
                        default={this.state.s.beam_y_pxl}
                    />
                    <NumberTextField
                        label={"Detector distance"}
                        callback={(val: number, err: boolean) => {
                            this.setState(prevState => ({
                                    s: {...prevState.s, detector_distance_mm: val},
                                    detector_distance_mm_err: err
                                }
                            ));
                        }}
                        units={"mm"}
                        min={0.1}
                        float={true}
                        default={this.state.s.detector_distance_mm}
                    />
                    <NumberTextField
                        label={"Energy"}
                        callback={(val: number, err: boolean) => {
                            this.setState(prevState => ({
                                    s: {...prevState.s, incident_energy_keV: val},
                                    incident_energy_kev_err: err
                                }
                            ));
                        }}
                        min={0.1}
                        max={500.0}
                        units={"keV"}
                        float={true}
                        default={this.state.s.incident_energy_keV}
                    />



                </Stack>
                <FormControl sx={{width: '90%'}}>
                    <RadioGroup
                        row
                        value={this.state.mode}
                        onChange={(event) => this.setState({mode: event.target.value as 'still' | 'rotation' | 'grid'})}>
                        <FormControlLabel value="still" control={<Radio/>} label="Still"/>
                        <FormControlLabel value="rotation" control={<Radio/>} label="Rotation"/>
                        <FormControlLabel value="grid" control={<Radio/>} label="Grid scan"/>
                    </RadioGroup>
                </FormControl>
                {this.state.mode === 'rotation' && (
                    <Stack direction="row" spacing={2} sx={{width: '90%'}}>
                        <NumberTextField
                            label="Start angle"
                            callback={(val: number) => this.setState(prevState => (
                                {goniometer : {...prevState.goniometer, start: val}}
                            ))}
                            units="°"
                            float={true}
                            default={this.state.goniometer.start}
                        />
                        <NumberTextField
                            label="Step"
                            callback={(val: number) => this.setState(prevState => (
                                {goniometer : {...prevState.goniometer, step: val}}
                            ))}
                            units="°"
                            float={true}
                            min={0.001}
                            default={this.state.goniometer.step}
                        />
                        <TextField
                            label="Axis name"
                            value={this.state.goniometer.name}
                            onChange={(e) => this.setState(prevState => (
                                {goniometer : {...prevState.goniometer, name: e.target.value}}
                                ))}
                        />
                    </Stack>
                )}
                {this.state.mode === 'grid' && (
                    <Stack direction="row" spacing={2} sx={{width: '90%'}}>
                        <NumberTextField
                            label="Grid elements (fast dim.)"
                            callback={(val: number) => this.setState((e) => this.setState(
                                prevState => (
                                    {grid : {...prevState.grid, n_fast: val}}
                                )))}
                            min={1}
                            default={this.state.grid.n_fast}
                        />
                        <NumberTextField
                            label="X step"
                            callback={(val: number) => this.setState((e) => this.setState(
                                prevState => (
                                    {grid : {...prevState.grid, step_x_um: val}}
                                )))}
                            units="μm"
                            float={true}
                            default={this.state.grid.step_x_um}
                        />
                        <NumberTextField
                            label="Y step"
                            callback={(val: number) => this.setState((e) => this.setState(
                                prevState => (
                                {grid : {...prevState.grid, step_y_um: val}}
                            )))}
                            units="μm"
                            float={true}
                            default={this.state.grid.step_y_um}
                        />
                        <FormControlLabel
                            control={
                                <Checkbox
                                    checked={this.state.grid.snake}
                                    onChange={(e) => this.setState(prevState => (
                                        {grid : {...prevState.grid, snake: e.target.checked}}
                                    ))}
                                />
                            }
                            label="Snake scan"
                        />
                        <FormControlLabel
                            control={
                                <Checkbox
                                    checked={this.state.grid.vertical}
                                    onChange={(e) => this.setState(prevState => (
                                        {grid : {...prevState.grid, vertical: e.target.checked}}
                                    ))}
                                />
                            }
                            label="Vertical scan"
                        />
                    </Stack>
                )}

                <Stack direction="row" spacing={2}>
                    <ButtonWithSnackbar
                        path={"/start"}
                        text={"start"}
                        disabled={this.error()}
                        input={JSON.stringify(this.getDatasetSettings())}
                        color={"primary"}
                    />
                    <ButtonWithSnackbar
                        path={"/trigger"}
                        text={"soft trigger"}
                        disabled={this.error()}
                        color={"primary"}
                    />
                </Stack>
            </Stack>
            <br/>
        </Paper>
    }
}

export default DataCollection;
