import {ChangeEvent, memo, useEffect, useState} from 'react';

import {Grid, Slider, Switch, Typography} from "@mui/material";
import {putConfigSpotFinding, spot_finding_settings} from "../client";
import SettingsPanel from "./SettingsPanel";
import _ from "lodash";

type MyProps = {
    s?: spot_finding_settings,
    update: () => void
};

const default_spot_finding_settings: spot_finding_settings = {
    enable: true,
    indexing: true,
    photon_count_threshold: 8,
    signal_to_noise_threshold: 3.0,
    min_pix_per_spot: 2,
    max_pix_per_spot: 50,
    high_resolution_limit: 2.5,
    low_resolution_limit: 50.0,
    quick_integration: false,
    high_resolution_limit_for_spot_count_low_res: 5.0,
    ice_ring_width_q_recipA: 0.02,
    high_res_gap_Q_recipA: 1.5
};

function putValues(x: spot_finding_settings) {
    putConfigSpotFinding({ body: x, throwOnError: true })
        .catch(error => console.log(error) );
}

function DataProcessingSettings({s: serverS, update}: MyProps) {
    const [s, setS] = useState<spot_finding_settings>(default_spot_finding_settings);
    const [lastDownloadedS, setLastDownloadedS] = useState<spot_finding_settings>(default_spot_finding_settings);
    const [highResGap, setHighResGap] = useState(1.5);

    // Only adopt the server copy when it actually changed, otherwise the
    // 1 s statistics poll would overwrite edits the user is making.
    useEffect(() => {
        if ((serverS !== undefined) && !_.isEqual(serverS, lastDownloadedS)) {
            setS(serverS);
            setLastDownloadedS(serverS);
            setHighResGap(serverS.high_res_gap_Q_recipA ?? highResGap);
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [serverS]);

    const apply = (next: spot_finding_settings) => {
        setS(next);
        putValues(next);
        update();
    };

    const setPhotonCountThreshold = (event: Event, newValue: number | number[]) =>
        apply({...s, photon_count_threshold: newValue as number});

    const setSignalToNoiseThreshold = (event: Event, newValue: number | number[]) =>
        apply({...s, signal_to_noise_threshold: newValue as number});

    const setMinPixPerSpot = (event: Event, newValue: number | number[]) =>
        apply({...s, min_pix_per_spot: newValue as number});

    const setLowResolutionLimit = (event: Event, newValue: number | number[]) =>
        apply({...s, low_resolution_limit: newValue as number});

    const setHighResolutionLimit = (event: Event, newValue: number | number[]) =>
        apply({...s, high_resolution_limit: newValue as number});

    const setHighResolutionLimitForCountingLowResSpots = (event: Event, newValue: number | number[]) =>
        apply({...s, high_resolution_limit_for_spot_count_low_res: newValue as number});

    const setIceRingWidth = (event: Event, newValue: number | number[]) =>
        apply({...s, ice_ring_width_q_recipA: newValue as number});

    const enableSpotFindingToggle = (event: ChangeEvent<HTMLInputElement>) =>
        apply({...s, enable: event.target.checked});

    const enableIndexingToggle = (event: ChangeEvent<HTMLInputElement>) =>
        apply({...s, indexing: event.target.checked});

    const enableQuickIntegrationToggle = (event: ChangeEvent<HTMLInputElement>) =>
        apply({...s, quick_integration: event.target.checked});

    const enableHighResGapToggle = (event: ChangeEvent<HTMLInputElement>) =>
        apply({...s, high_res_gap_Q_recipA: event.target.checked ? highResGap : undefined});

    const handleHighResGap = (event: Event, newValue: number | number[]) => {
        const v = newValue as number;
        setHighResGap(v);
        apply({...s, high_res_gap_Q_recipA: v});
    };

    return (
        <SettingsPanel title="Spot finding parameters" sx={{ height: 800 }}>
                <Grid container spacing={0}>

                    <Grid item xs={1}/>
                    <Grid item xs={10}>
                        <Switch onChange={enableSpotFindingToggle} checked={s.enable}/>
                        Spot finding
                        <br/><br/>

                        <Typography gutterBottom> Count threshold </Typography>
                        <Slider disabled={!s.enable}
                                value={Number(s.photon_count_threshold)}
                                onChange={setPhotonCountThreshold}
                                min={1} max={50} step={1} valueLabelDisplay="auto"/>

                        <br/><Typography> Signal-to-noise threshold </Typography>
                        <Slider disabled={!s.enable}
                                value={Number(s.signal_to_noise_threshold)}
                                onChange={setSignalToNoiseThreshold}
                                min={2}
                                max={10}
                                step={0.5}
                                valueLabelDisplay="auto"
                                valueLabelFormat={(value) => value.toFixed(1)}
                        />

                        <br/><Typography> Minimum pixel / spot </Typography>
                        <Slider disabled={!s.enable}
                                value={Number(s.min_pix_per_spot)}
                                onChange={setMinPixPerSpot}
                                min={1} max={8} step={1} valueLabelDisplay="auto"/>
                        <Typography> Low resolution limit [&#8491;] </Typography>
                        <Slider disabled={!s.enable}
                                value={Number(s.low_resolution_limit)}
                                onChange={setLowResolutionLimit}
                                min={10} max={100} step={0.1} valueLabelDisplay="auto"
                                valueLabelFormat={(value) => value.toFixed(1)}
                        />

                        <Typography> High resolution limit [&#8491;] </Typography>
                        <Slider disabled={!s.enable}
                                value={Number(s.high_resolution_limit)}
                                onChange={setHighResolutionLimit}
                                min={1} max={5} step={0.1} valueLabelDisplay="auto"
                                valueLabelFormat={(value) => value.toFixed(1)}
                        />
                        <Typography> High resolution limit for counting low resolution spots [&#8491;] </Typography>
                        <Slider disabled={!s.enable}
                                value={Number(s.high_resolution_limit_for_spot_count_low_res)}
                                onChange={setHighResolutionLimitForCountingLowResSpots}
                                min={2} max={8} step={0.1} valueLabelDisplay="auto"
                                valueLabelFormat={(value) => value.toFixed(1)}
                        />
                        <Typography> Ice ring width in Q-space [&#8491;<sup>-1</sup>] </Typography>
                        <Slider disabled={!s.enable}
                                value={Number(s.ice_ring_width_q_recipA)}
                                onChange={setIceRingWidth}
                                min={0.0} max={0.2} step={0.001} valueLabelDisplay="auto"
                                valueLabelFormat={(value) => value.toFixed(3)}
                        />

                        <Switch
                            onChange={enableHighResGapToggle}
                            checked={s.high_res_gap_Q_recipA !== undefined}
                            disabled={!s.enable}
                        />
                        High‑res gap Q-space filter [&#8491;<sup>-1</sup>]
                        <Typography/>
                        <Slider
                            disabled={!s.enable || s.high_res_gap_Q_recipA === undefined}
                            value={Number(s.high_res_gap_Q_recipA ?? highResGap)}
                            onChange={handleHighResGap}
                            min={0.1}
                            max={5.0}
                            step={0.01}
                            valueLabelDisplay="auto"
                            valueLabelFormat={(value) => value.toFixed(2)}
                        />

                        <br/><br/>
                        <Switch onChange={enableIndexingToggle}
                                checked={s.indexing}
                                disabled={!s.enable}/>
                        Indexing <br/><br/>
                        <Switch onChange={enableQuickIntegrationToggle}
                                checked={s.quick_integration}
                                disabled={!s.enable}/>
                        Quick MX integration
                    </Grid>
                    <Grid item xs={1}/>
                </Grid>
        </SettingsPanel>
    );
}

export default memo(DataProcessingSettings);
