import React, {Fragment} from "react";
import {createStyles, Theme, withStyles, WithStyles, WithTheme} from "@material-ui/core";
import ListSubheader from "@material-ui/core/ListSubheader";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import Collapse from "@material-ui/core/Collapse";
import Checkbox from "@material-ui/core/Checkbox";
import Divider from "@material-ui/core/Divider";
import Button from "@material-ui/core/Button";
import {Instrument, Inverter, MeasurementOptions} from "../MySitePageTypes";

const styles = (theme: Theme) =>
    createStyles({
        root: {
            width: '100%',
            maxWidth: 360,
            backgroundColor: theme.palette.background.paper,
        },
        nested: {
            paddingLeft: theme.spacing(4),
        },
    });

type Element = {
    value: number,
    isOpen: boolean,
    isChecked: boolean
}

type Props = {
    handleConnectedChecked: (index: number) => void
    handleNotConnectedChecked: (index: number) => void
    handleClick: (index: number) => void
    handleSubmit: () => void
    options: MeasurementOptions
} & WithStyles<typeof styles> & WithTheme
type State = {
    withInverter?: Inverter[],
    withoutInverter?: Instrument[]
}

class MeasurementPicker extends React.Component<Props, State> {

    handleClick = (index: number) => this.props.handleClick(index);

    handleConnectedChecked = (index: number) => this.props.handleConnectedChecked(index);

    handleNotConnectedChecked = (index: number) => this.props.handleNotConnectedChecked(index);

    isAnyInverterConnectedChecked = (): boolean => !!this.props.options.withInverter?.find((inv) => inv.isChecked);

    isAnyInverterNotConnectedChecked = (): boolean => !!this.props.options.withoutInverter?.find((ins) => ins.isChecked);

    handleSubmit = () => this.props.handleSubmit();

    render() {
        return (
            <>
                <List
                    component="nav"
                    aria-labelledby="nested-list-subheader"
                    className={this.props.classes.root}
                >
                    <ListSubheader component="div" id="subheader-1"> Connected to Inverters </ListSubheader>
                    {this.props.options.withInverter ? this.renderConnectedToInverterSection(this.props.options.withInverter) : "No sensors fully connected to inverter available"}
                    {(this.props.options.withInverter && this.props.options.withoutInverter) ?
                        <Divider variant={"middle"}/> : undefined}
                    <ListSubheader component="div" id="subheader-2"> Not Connected to Inverters </ListSubheader>
                    {this.props.options.withoutInverter ? this.renderNotConnectedToInverterSection(this.props.options.withoutInverter) : "No sensors not connected to inverter available"}
                </List>
                <Button
                    disabled={!(this.isAnyInverterConnectedChecked() || this.isAnyInverterNotConnectedChecked())}
                    variant="contained"
                    color="primary"
                    onClick={this.handleSubmit}>
                    Display Graphs
                </Button>
            </>)
    }

    private renderNotConnectedToInverterSection = (notConnectedInstruments: Instrument[]) => {
        return (
            notConnectedInstruments.map((ins, index) => {
                const labelId = `checkbox-list-label-${ins}`;
                return <ListItem key={`key-inverter-${ins.id}`} button onClick={() => {
                }}>
                    <ListItemIcon>
                        <Checkbox
                            edge="start"
                            checked={ins.isChecked}
                            onChange={() => this.handleNotConnectedChecked(index)}
                            tabIndex={-1}
                            disabled={!ins.isChecked && this.isAnyInverterConnectedChecked()}
                            disableRipple
                            inputProps={{'aria-labelledby': labelId}}
                        />
                    </ListItemIcon>
                    <ListItemText
                        primary={this.generateInstrumentListItemText(ins)}/>
                </ListItem>

            }))
    };

    private generateInstrumentListItemText = (ins: Instrument) => {
        if(ins.monitoredAreas.length > 0) return `Sensor #${ins.id} (Monitored areas: ${ins.monitoredAreas.map((ma) => `#${ma.id}`).join(", ")})`;
        else return `Sensor #${ins.id} (No monitored Areas)`
    };

    private renderConnectedToInverterSection = (inverters: Inverter[]) => {
        return (
            inverters.map((inv, index) => {
                const labelId = `checkbox-list-label-${inv}`;
                return <Fragment key={`key-fragment-${index}`}>
                    <ListItem key={`key-inverter-${inv.inverterId}`} button onClick={() => this.handleClick(index)}>
                        <ListItemIcon>
                            <Checkbox
                                edge="start"
                                checked={inv.isChecked}
                                onChange={() => this.handleConnectedChecked(index)}
                                tabIndex={-1}
                                disabled={!inv.isChecked && this.isAnyInverterConnectedChecked() || this.isAnyInverterNotConnectedChecked()}
                                disableRipple
                                inputProps={{'aria-labelledby': labelId}}
                            />
                        </ListItemIcon>
                        <ListItemText primary={`Sensors of Inverter #${inv.inverterId.toString()}`}/>
                        {inv.isOpen ? <ExpandLess/> : <ExpandMore/>}
                    </ListItem>
                    <Collapse in={inv.isOpen} timeout="auto" unmountOnExit>
                        <List component="div" disablePadding>
                            {inv.instruments.map((ins) => {
                                return <ListItem key={`key-instrument-nested-${ins.id}`} button
                                                 className={this.props.classes.nested}>
                                    <ListItemText primary={this.generateInstrumentListItemText(ins)}/></ListItem>
                            })}
                        </List>
                    </Collapse>
                </Fragment>
            })
        )
    }
}

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