import * as React from "react";
import {createStyles, Theme, WithStyles, withStyles, WithTheme} from "@material-ui/core";
import Grid from "@material-ui/core/Grid";
import Button from "@material-ui/core/Button";
import {createApiRequestStore} from "../../../api/ApiRequestStore";
import {InsIvnMonitoredArea, Instrument} from "./SensorsPageTypes";
import {NewInstrumentDialog} from "./components/NewInstrumentDialog";
import InstrumentCard from "./components/InstrumentCard";
import {SiteDescription} from "../../../common/appRoutes";
import Loader from "../../../common/Loader";
import {Autocomplete} from "@material-ui/lab";
import TextField from "@material-ui/core/TextField/TextField";

const styles = (theme: Theme) =>
    createStyles({
        root: {
            flexGrow: 1,
        },
        paper: {
            padding: theme.spacing(2),
            textAlign: 'center',
            color: theme.palette.text.secondary,
        },
    });


type InstrumentsPageProps = {
    filteredIds?: number[]
    onSectionChange: (route: SiteDescription, params?: number[]) => void
} & WithStyles<typeof styles> & WithTheme


type InstrumentsPageState = {
    newInstrumentDialogOpen: boolean
    instrumentCards: Instrument[]
    filteredInstruments: Instrument[]
    availableMonitoredAreas: InsIvnMonitoredArea[]
    isLoadingData: boolean
}


class SensorsPage extends React.Component<InstrumentsPageProps, InstrumentsPageState> {
    requestStore = createApiRequestStore();

    readonly state: InstrumentsPageState = {
        newInstrumentDialogOpen: false,
        instrumentCards: [],
        filteredInstruments: [],
        availableMonitoredAreas: [],
        isLoadingData: false
    };

    private handleClickOpen = () => {
        this.setState({
            newInstrumentDialogOpen: true
        })
    };

    private handleClose = () => {
        this.setState({
            newInstrumentDialogOpen: false
        })
    };

    private handleSubmit = (newInstrument: Instrument) => {
        this.requestStore.createNewInstrument(Object.assign(newInstrument))
            .then(response => {
                if (response) {
                    this.handleClose();
                    this.loadInstruments(true);
                }
            }).catch((error) => {
            alert("something went wrong and new sensor was not created.")
        });
    };

    private loadInstruments = (isInitialLoad: boolean) => {
        this.setState({
            ...this.state,
            isLoadingData: true
        });
        this.requestStore.loadInstruments()
            .then(response => {
                this.setState({
                    ...this.state,
                    instrumentCards: response.instruments.map((ins): Instrument => {
                        return {...ins, isExpanded: false}
                    }),
                    availableMonitoredAreas: response.availableMonitoredAreas,
                    isLoadingData: false
                }, () => this.setFilteredInstrumentsToState(this.state.instrumentCards, isInitialLoad))
            })
            .catch(error => {
                alert("No instruments loaded for current user.");
                this.setState({
                    ...this.state,
                    isLoadingData: true
                });
            })
    };

    private setFilteredInstrumentsToState = (reloadedInstruments: Instrument[], isInitialLoad: boolean): void => {
        console.log(reloadedInstruments);
        this.setState({
            ...this.state,
            filteredInstruments: this.expandedInstruments(reloadedInstruments, isInitialLoad)
        });
    };

    private expandedInstruments = (reloadedInstruments: Instrument[], isFirstLoad: boolean): Instrument[] => {
        const filteredInstrumentById = reloadedInstruments.find((value => this.props.filteredIds ? value.id === this.props.filteredIds[0] : undefined));
        const previousStateFilteredInstruments = this.state.filteredInstruments;

        if (isFirstLoad) {
            return filteredInstrumentById ? [{
                ...filteredInstrumentById,
                isExpanded: true
            }] : []
        } else {
            return previousStateFilteredInstruments.map((ma): Instrument => {
                const reloadedIns = reloadedInstruments.find((insById) => insById.id === ma.id);
                return {
                    ...reloadedIns!,
                    isExpanded: ma.isExpanded
                }
            });
        }
    };


    private handleUpdate = (instrument: Instrument) => {
        this.requestStore.updateInstrument(Object.assign(instrument))
            .then(response => {
                this.loadInstruments(false)
            })
            .catch(error => {
                alert("Could not update instrument.")
            })
    };

    private handleCardExpand = (updatedInstrument: Instrument) => {
        this.setState({
            ...this.state,
            filteredInstruments: this.state.filteredInstruments.map((value): Instrument => {
                if (value.id === updatedInstrument.id) {
                    return {...value, isExpanded: !value.isExpanded}
                } else return value
            })
        })
    };


    componentDidMount() {
        this.loadInstruments(true)
    }

    render() {
        return <div className={this.props.classes.root}>
            <Grid container spacing={3}>
                <Grid item xs={3}>
                    <div>
                        <Button variant="outlined" color="primary" onClick={this.handleClickOpen}>
                            New Sensor
                        </Button>
                        <NewInstrumentDialog dialogOpen={this.state.newInstrumentDialogOpen}
                                             handleSubmit={this.handleSubmit} handleClose={this.handleClose}/>
                    </div>
                </Grid>
                {this.state.isLoadingData ? <Grid item sm={12} xs={12}><Loader/></Grid> : this.renderContent()}
            </Grid>
        </div>
    }


    private renderContent() {
        return <>
            <Grid item xs={6}>
                <div>
                    <Autocomplete
                        multiple
                        limitTags={2}
                        id="multiple-limit-tags"
                        options={this.state.instrumentCards}
                        getOptionLabel={(option) => this.createOptionLabel(option)}
                        value={this.state.filteredInstruments}
                        onChange={this.handleOnChange}
                        getOptionSelected={(option, value) => option.id === value.id}
                        renderInput={(params) => (
                            <TextField {...params} variant="outlined" label="Sensor Description"
                                       placeholder="Sensors" name={"description"}/>
                        )}
                    />
                </div>
            </Grid>
            {this.state.filteredInstruments?.map((value, index) => <InstrumentCard key={value.id} instrument={value}
                                                                                   availableMonitoredAreas={this.state.availableMonitoredAreas}
                                                                                   cardIndex={index}
                                                                                   handleUpdate={this.handleUpdate}
                                                                                   isExpanded={value.isExpanded}
                                                                                   handleExpanded={this.handleCardExpand}
                                                                                   onSectionChange={this.props.onSectionChange}
            />)}
        </>;
    }

    private createOptionLabel = (option: Instrument) => {
        return `Sensor ${option.id} ${this.createMonitoredAreasLabel(option)}`;
    };

    private createMonitoredAreasLabel = (option: Instrument) => {
        const monitoredAreas = option.monitoredAreas;
        if (monitoredAreas.length > 0) {
            return  "monitored areas: " + monitoredAreas.map(ma => `Area ${ma.id} - '${ma.description}'`)
        } else return ""
    };

    private handleOnChange = (event: any, values: any) => {
        this.setState({
            ...this.state,
            filteredInstruments: values
        })
    };
}


export default withStyles(styles, {withTheme: true})(SensorsPage);