import React, {Fragment} from 'react';
import clsx from 'clsx';
import {createStyles, Theme, ThemeProvider, WithStyles, WithTheme} from '@material-ui/core/styles';
import Drawer from '@material-ui/core/Drawer';
import List from '@material-ui/core/List';
import Divider from '@material-ui/core/Divider';
import IconButton from '@material-ui/core/IconButton';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import MenuIcon from '@material-ui/icons/Menu';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import Typography from "@material-ui/core/Typography";
import {RouteComponentProps, Switch, withRouter} from "react-router";
import {PrivateRoute} from "../../common/PrivateRoute";
import {OtherSites} from "../generalSection/OtherSites";
import {UserRoles} from "../administrationSection/UserRoles";
import {AppRoutes, SiteDescription} from "../../common/appRoutes";
import Sensors from "../administrationSection/sensors/SensorsPage";
import MonitoredAreas from "../administrationSection/monitoredAreas/MonitoredAreasPage";
import {createApiRequestStore} from "../../api/ApiRequestStore";
import {UserSummary} from "../../api/RequestBodyData";
import Inverters from "../administrationSection/inverters/InverterConnectionPage";
import MySitePage from "../generalSection/mySite/MySitePage";
import {ErrorDialogData} from "../../common/errorHandling/ErrorMapper";
import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction";
import {ListItemAvatar} from "@material-ui/core";
import Avatar from "@material-ui/core/Avatar";
import MenuItem from "@material-ui/core/MenuItem";
import Menu from "@material-ui/core/Menu";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import CssBaseline from "@material-ui/core/CssBaseline";
import withStyles from "@material-ui/core/styles/withStyles";
import AddIcon from "@material-ui/core/SvgIcon/SvgIcon";


const drawerWidth = 240;

const styles = (theme: Theme) =>
    createStyles({
        root: {
            display: 'flex',
        },
        menuButton: {},
        hide: {
            display: 'none',
        },
        subtitle: {
            padding: theme.spacing(1, 2),
            height: theme.spacing(4)
        },
        drawer: {
            width: drawerWidth,
            flexShrink: 0,
            whiteSpace: 'nowrap',
            backgroundColor: theme.palette.primary.light,
            color: theme.palette.text.primary
        },
        drawerOpen: {
            width: drawerWidth,
            transition: theme.transitions.create('width', {
                easing: theme.transitions.easing.sharp,
                duration: theme.transitions.duration.enteringScreen,
            }),
            backgroundColor: theme.palette.primary.light,
            color: theme.palette.text.primary
        },
        drawerClose: {
            transition: theme.transitions.create('width', {
                easing: theme.transitions.easing.sharp,
                duration: theme.transitions.duration.leavingScreen,
            }),
            overflowX: 'hidden',
            width: theme.spacing(7) + 1,
            [theme.breakpoints.up('sm')]: {
                width: theme.spacing(9) + 1,
            },
            backgroundColor: theme.palette.primary.light,
            color: theme.palette.text.primary
        },
        toolbar: {
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'flex-end',
            padding: theme.spacing(0, 2),
            // necessary for content to be below app bar
            ...theme.mixins.toolbar,
            backgroundColor: theme.palette.primary.dark
        },
        content: {
            flexGrow: 1,
            padding: theme.spacing(3)
        },
    });


type MainPageProps = {
    currentUser: UserSummary
    isAuthenticated: boolean
    appRoutes: Map<AppRoutes, SiteDescription>
    handleErrorDialogOpen: (dialogData: ErrorDialogData) => void
    handleErrorDialogClose: () => void
    handleLogout: () => void
} & WithStyles<typeof styles> & WithTheme & RouteComponentProps


type MainPageState = {
    drawerOpen: boolean,
    errorDialogOpen: boolean,
    errorDialogData?: ErrorDialogData,
    selectedSite: SiteDescription,
    menuAnchorElement: null | HTMLElement,
    filteredIds?: number[]
}


class MainPage extends React.Component<MainPageProps, MainPageState> {
    requestStore = createApiRequestStore();

    readonly state: MainPageState = {
        drawerOpen: true,
        errorDialogOpen: false,
        errorDialogData: undefined,
        selectedSite: {} as SiteDescription,
        menuAnchorElement: null,
        filteredIds: undefined
    };

    private handleErrorDialogOpen = this.props.handleErrorDialogOpen;

    private handleErrorDialogClose = this.props.handleErrorDialogClose;

    private handleLogout = this.props.handleLogout;


    private handleAccountClick = (event: React.MouseEvent<HTMLButtonElement>) => {
        this.setState({
            ...this.state,
            menuAnchorElement: event.currentTarget,
        })
    };

    private handleDrawerOpen = () => {
        this.setState({drawerOpen: true});
    };

    private handleClose = () => {
        this.setState({
            ...this.state,
            menuAnchorElement: null,
        })
    };

    private handleDrawerClose = () => {
        this.setState({drawerOpen: false});
    };

    private onSectionChange = (route: SiteDescription, params?: number[]) => {
        console.log("params are: ", params)
        this.setState({
            ...this.state,
            selectedSite: route,
            filteredIds: params
        });
        this.props.history.push(route.siteUrl)
    };

    private renderMainContent = () => {
        return <main
            className={this.props.classes.content}>
            <ThemeProvider theme={this.props.theme}>
                <Switch>
                    <PrivateRoute isAuthenticated={this.props.isAuthenticated}
                                  path={this.props.appRoutes.get(AppRoutes.MySite)!.siteUrl}
                                  render={(props => <MySitePage handleErrorDialogClose={this.handleErrorDialogClose}
                                                                handleErrorDialogOpen={this.handleErrorDialogOpen}
                                                                drawerWidth={drawerWidth}
                                                                {...props}/>)}/>
                    <PrivateRoute isAuthenticated={this.props.isAuthenticated}
                                  path={this.props.appRoutes.get(AppRoutes.OtherSites)!.siteUrl}
                                  render={(props => <OtherSites  {...props}/>)}/>
                    <PrivateRoute isAuthenticated={this.props.isAuthenticated}
                                  path={this.props.appRoutes.get(AppRoutes.Sensors)!.siteUrl}
                                  render={(props => <Sensors filteredIds={this.state.filteredIds} onSectionChange={this.onSectionChange} {...props}/>)}/>
                    <PrivateRoute isAuthenticated={this.props.isAuthenticated}
                                  path={this.props.appRoutes.get(AppRoutes.MonitoredAreas)!.siteUrl}
                                  render={(props => <MonitoredAreas filteredIds={this.state.filteredIds} onSectionChange={this.onSectionChange} {...props}/>)}/>
                    <PrivateRoute isAuthenticated={this.props.isAuthenticated}
                                  path={this.props.appRoutes.get(AppRoutes.InverterConnection)!.siteUrl}
                                  render={(props => <Inverters onSectionChange={this.onSectionChange} {...props}/>)}/>
                    <PrivateRoute isAuthenticated={this.props.isAuthenticated}
                                  path={this.props.appRoutes.get(AppRoutes.UserRoles)!.siteUrl}
                                  render={(props => <UserRoles  {...props}/>)}/>
                </Switch>
            </ThemeProvider>
        </main>;
    };

    private renderLeftMenu = () => {
        return <Drawer
            variant="permanent"
            className={clsx(this.props.classes.drawer, {
                [this.props.classes.drawerOpen]: this.state.drawerOpen,
                [this.props.classes.drawerClose]: !this.state.drawerOpen,
            })}
            classes={{
                paper: clsx({
                    [this.props.classes.drawerOpen]: this.state.drawerOpen,
                    [this.props.classes.drawerClose]: !this.state.drawerOpen,
                }),
            }}
        >


            <div className={this.props.classes.toolbar}>
                {this.state.drawerOpen ? (
                    <Fragment>
                        <IconButton onClick={this.handleDrawerClose}>
                            {this.props.theme.direction === 'ltr' ? <ChevronLeftIcon/> : <ChevronRightIcon/>}
                        </IconButton>
                        <Typography variant="h6">
                            MY SOLAR SCAN
                        </Typography>
                    </Fragment>

                ) : <IconButton
                    color="inherit"
                    aria-label="open drawer"
                    onClick={this.handleDrawerOpen}
                    edge="start"
                    className={clsx(this.props.classes.menuButton, this.state.drawerOpen && this.props.classes.hide)}
                >
                    <MenuIcon className={this.props.classes.menuButton}/>
                </IconButton>}


            </div>

            <List>
                <ListItem>
                    <ListItemAvatar><Avatar/></ListItemAvatar>
                    <ListItemText>{`Logged: ${this.props.currentUser.username}`}</ListItemText>
                    <ListItemSecondaryAction>
                        <IconButton
                            aria-controls="simple-menu"
                            aria-haspopup="true"
                            onClick={this.handleAccountClick}
                        ><ExpandMoreIcon/>
                        </IconButton>
                        <Menu
                            id="simple-menu"
                            anchorEl={this.state.menuAnchorElement}
                            keepMounted
                            open={Boolean(this.state.menuAnchorElement)}
                            onClose={this.handleClose}
                        >
                            <MenuItem key={"key-logout"} onClick={this.handleLogout}> Logout</MenuItem>
                        </Menu>
                    </ListItemSecondaryAction>
                </ListItem>
                <Divider/>
                {this.renderGeneralSectionMenu()}
                <Divider/>
                <div className={this.props.classes.subtitle}>
                    {this.state.drawerOpen ? <Typography variant={'subtitle1'}>Administration</Typography> : <div/>}
                </div>
                {this.renderAdminSectionMenu()}
            </List>
        </Drawer>
            ;
    };

    private renderAdminSectionMenu = () => {
        return this.createListItems([
            this.props.appRoutes.get(AppRoutes.Sensors)!,
            this.props.appRoutes.get(AppRoutes.MonitoredAreas)!,
            this.props.appRoutes.get(AppRoutes.InverterConnection)!,
            this.props.appRoutes.get(AppRoutes.UserRoles)!
        ])
    };

    private renderGeneralSectionMenu = () => {
        return this.createListItems([
            this.props.appRoutes.get(AppRoutes.MySite)!,
            this.props.appRoutes.get(AppRoutes.OtherSites)!
        ])

    };

    private createListItems = (routes: SiteDescription[]) => {
        return routes.map((route) => (
            <ListItem selected={this.state.selectedSite === route} onClick={() => this.onSectionChange(route)}
                      button
                      key={route!.siteName}>
                <ListItemIcon>{route!.siteIcon!}</ListItemIcon>
                <ListItemText>{route!.siteName}</ListItemText>
            </ListItem>
        ))
    };

    render() {
        return <div className={this.props.classes.root}>
            <CssBaseline/>
            {this.renderLeftMenu()}
            {this.renderMainContent()}
        </div>

    }
}

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