import clsx from 'clsx';

import Grid from "@material-ui/core/Grid";
import Card from "@material-ui/core/Card";
import CardHeader from "@material-ui/core/CardHeader";
import CardContent from "@material-ui/core/CardContent";
import TableContainer from "@material-ui/core/TableContainer";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableRow from "@material-ui/core/TableRow";
import TableCell from "@material-ui/core/TableCell";
import {createStyles, Theme, Tooltip, withStyles, WithStyles, WithTheme} from "@material-ui/core";
import FiberSmartRecordIcon from '@material-ui/icons/FiberSmartRecord';
import CardActions from "@material-ui/core/CardActions";
import Switch from "@material-ui/core/Switch";
import IconButton from "@material-ui/core/IconButton";
import Collapse from "@material-ui/core/Collapse";
import Divider from "@material-ui/core/Divider";
import * as React from "react";
import {InsIvnMonitoredArea, Instrument, InstrumentState} from "../SensorsPageTypes";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import DoneIcon from "@material-ui/icons/Done";
import EditIcon from "@material-ui/icons/Edit";
import CloseIcon from '@material-ui/icons/Close';
import TextField from "@material-ui/core/TextField";
import MonitoredAreasCardSeciton from "../../common/MonitoredAreasCardSeciton";
import {AppRoutes, appRoutes, SiteDescription} from "../../../../common/appRoutes";
import Chip from "@material-ui/core/Chip";
import Typography from "@material-ui/core/Typography";
import {MonitoredArea} from "../../monitoredAreas/MonitoredAreaPageTypes";


const styles = (theme: Theme) =>
    createStyles({
        paper: {
            padding: theme.spacing(2),
            textAlign: 'center',
            color: theme.palette.text.secondary,
        },
        tableCell: {
            borderBottom: "none"
        },
        expand: {
            transform: "rotate(0deg)",
            marginLeft: "auto",
            transition: theme.transitions.create("transform", {
                duration: theme.transitions.duration.shortest
            })
        },
        expandOpen: {
            transform: "rotate(180deg)"
        },
    });

type InstrumentsCardProps = {
    cardIndex: number,
    instrument: Instrument,
    availableMonitoredAreas: InsIvnMonitoredArea[]
    handleUpdate: (updatedInstrument: Instrument) => void
    isExpanded: boolean
    handleExpanded: (updatedInstrument: Instrument) => void
    onSectionChange: (route: SiteDescription, params?: number[]) => void
} & WithStyles<typeof styles> & WithTheme


type InstrumentsCardState = {
    isExpanded: boolean,
    isEdited: boolean,
    toggleState: boolean,
    instrument: Instrument
}


class InstrumentCard extends React.Component<InstrumentsCardProps, InstrumentsCardState> {
    readonly state: InstrumentsCardState = {
        isExpanded: false,
        isEdited: false,
        toggleState: false,
        instrument: this.props.instrument
    };

    private isEntryOfPrimitiveType = (value: any) => {
        return typeof value === "string" || typeof value === "number";
    };

    private handleDialogChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
        this.setState({
                ...this.state,
                instrument: {
                    ...this.state.instrument,
                    [event.currentTarget.name]: event.target.value
                }
            }
        )
    };

    private editInstrumentProperties = () => {
        if (this.state.isEdited) {
            this.props.handleUpdate(this.state.instrument)
        }

        this.setState({
            ...this.state,
            isEdited: !this.state.isEdited
        })
    };

    private discardChanges = () => {
        this.setState({
            ...this.state,
            isEdited: !this.state.isEdited,
            instrument: this.props.instrument,
            toggleState: this.isSwitchOn(this.props.instrument.state)
        })
    };

    private handleExpandClick = () => {
        this.props.handleExpanded(this.props.instrument);
    };

    private handleStateSwitchChange = (event: React.ChangeEvent<HTMLInputElement>) => {

        const newSwitchState = this.handleSwitchChangeBasedOnPreviousState(this.state.instrument.state);
        this.setState({
            ...this.state,
            instrument: {
                ...this.state.instrument,
                state: newSwitchState ? newSwitchState : this.state.instrument.state
            },
            toggleState: this.isSwitchOn(newSwitchState)
        })
    };

    private isSwitchOn = (switchState: InstrumentState | undefined): boolean => {
        return (switchState === InstrumentState.MEASURING)
    };

    private handleSwitchChangeBasedOnPreviousState = (previousState: InstrumentState): InstrumentState | undefined => {
        switch (previousState) {
            case InstrumentState.CREATED:
                return InstrumentState.MEASURING;
            case InstrumentState.MEASURING:
                return InstrumentState.STOPPED;
            case InstrumentState.STOPPED:
                return InstrumentState.MEASURING;
            default:
                return undefined
        }
    };

    private getColorFromInstrumentState = () => {
        switch (this.state.instrument.state) {
            case InstrumentState.CREATED:
                return 'disabled';
            case InstrumentState.MEASURING:
                return 'primary';
            case InstrumentState.MALFUNCTIONING:
                return 'error';
            case InstrumentState.STOPPED:
                return 'error';
            case InstrumentState.DEPRECATED:
                return 'disabled';
            default:
                return 'disabled'
        }
    };

    private renderInstrumentTableRows = () => {
        return <>
            {Object.entries(this.state.instrument).map(([key, value]) => {
                    return this.renderTableRow(key, value)
                }
            )}
        </>;
    };

    private renderTableRow = (key: string, value: any) => {
        if (this.isEntryOfPrimitiveType(value) && key !== "state" && key !== "id")
            return (<TableRow key={key}>
                <TableCell
                    className={this.props.classes.tableCell}
                    component="th"
                    scope="row"
                >
                    {key}
                </TableCell>
                <TableCell className={this.props.classes.tableCell}
                           align="right">{this.state.isEdited ?
                    <TextField
                        autoFocus
                        required
                        margin="dense"
                        id={key}
                        label={key.toUpperCase()}
                        type={typeof value}
                        fullWidth
                        name={key}
                        value={value}
                        onChange={this.handleDialogChange}
                    /> : value ? value : "without value"}
                </TableCell>
            </TableRow>);
    };

    componentDidMount(): void {
        this.setState({
            ...this.state,
            toggleState: this.isSwitchOn(this.props.instrument.state)
        })
    }

    render() {
        return <Grid item sm={6} xs={12}>
            <Card>
                <CardHeader title={`Sensor #${this.props.instrument.id}`}/>
                <CardContent>
                    <Typography display={"inline"}>Monitored Areas: </Typography>
                    {this.renderMonitoredAreaChips()}
                </CardContent>
                <CardContent>
                    <TableContainer>
                        <Table aria-label="sensor state table">
                            <TableBody>
                                <TableRow key="state">
                                    <TableCell
                                        className={this.props.classes.tableCell}
                                        component="th"
                                        scope="row"
                                    >
                                        State
                                    </TableCell>
                                    <TableCell align="right" className={this.props.classes.tableCell}>
                                        <Tooltip title={this.state.instrument.state} aria-label="add">
                                            <FiberSmartRecordIcon color={this.getColorFromInstrumentState()}/>
                                        </Tooltip>
                                    </TableCell>
                                </TableRow>
                            </TableBody>
                        </Table>
                    </TableContainer>
                </CardContent>
                <CardActions disableSpacing>
                    <Switch
                        checked={this.state.toggleState}
                        onChange={this.handleStateSwitchChange}
                        name="checkedA"
                        inputProps={{"aria-label": "secondary checkbox"}}
                        disabled={!this.state.isEdited}
                    />
                    <IconButton
                        className={clsx(this.props.classes.expand, {
                            [this.props.classes.expandOpen]: this.props.isExpanded
                        })}
                        onClick={this.handleExpandClick}
                        aria-expanded={this.props.isExpanded}
                        aria-label="show more"
                    >
                        <ExpandMoreIcon/>
                    </IconButton>
                </CardActions>

                <Collapse in={this.props.isExpanded} timeout="auto" unmountOnExit>
                    <Divider variant="middle"/>
                    <CardContent>
                        <TableContainer>
                            <Table
                                size="small"
                                aria-label="simple table"
                            >
                                <TableBody>
                                    {this.renderInstrumentTableRows()}
                                </TableBody>
                            </Table>
                        </TableContainer>
                    </CardContent>

                    <Divider variant="middle"/>
                    <MonitoredAreasCardSeciton isEdited={this.state.isEdited}
                                               monitoredAreas={this.props.instrument.monitoredAreas}
                                               availableMonitoredAreas={this.props.availableMonitoredAreas}
                    />
                    <CardActions disableSpacing>
                        <IconButton aria-label="add to favorites"
                                    onClick={this.editInstrumentProperties}>
                            {this.state.isEdited ? <DoneIcon/> : <EditIcon/>}
                        </IconButton>
                        <IconButton aria-label="add to favorites"
                                    onClick={this.discardChanges}>
                            {this.state.isEdited ? <CloseIcon/> : undefined}
                        </IconButton>
                    </CardActions>
                </Collapse>
            </Card>
        </Grid>
    }

    componentDidUpdate(prevProps: InstrumentsCardProps, prevState: InstrumentsCardState) {
        if (this.props.instrument !== prevState.instrument && this.props.instrument !== prevProps.instrument) {
            this.setState({...this.state, instrument: this.props.instrument})
        }
    }

    private renderMonitoredAreaChips = () => {
        const connectedAreas = this.props.instrument.monitoredAreas;
        return <>
            {connectedAreas.length > 0? this.props.instrument.monitoredAreas.map(ma => <Chip
                key={`key-chip-${ma.id}-with-area`}
                color={'primary'}
                onClick={() => this.props.onSectionChange(appRoutes.get(AppRoutes.MonitoredAreas)!, this.getMaIdsForFilter(ma, this.props.instrument.monitoredAreas))}
                disabled={this.state.isEdited}
                icon={appRoutes.get(AppRoutes.MonitoredAreas)!.siteIcon}
                label={`'${ma.description}' (#${ma.id})`}/>):
                <Chip
                    key={`key-chip-without-area`}
                    disabled={true}
                    color={'primary'}
                    icon={appRoutes.get(AppRoutes.MonitoredAreas)!.siteIcon}
                    label={`No Area`}/>
            }
        </>;
    };


    private getMaIdsForFilter = (clickedMa: InsIvnMonitoredArea, monitoredAreas: InsIvnMonitoredArea[]): number[] => {
        const allMas = monitoredAreas;
        allMas.splice(monitoredAreas.indexOf(clickedMa),1);
        return [clickedMa.id, ...allMas.map(value => value.id)]
    };
}


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