import {
  Avatar,
  Button,
  CircularProgress,
  createStyles,
  Divider,
  Drawer,
  Grid,
  IconButton,
  List,
  ListItem,
  ListItemIcon,
  ListItemSecondaryAction,
  ListItemText,
  Theme,
  Tooltip,
  Typography,
  useTheme
} from "@mui/material";
import { makeStyles } from "@mui/styles"
import { Remove } from "@mui/icons-material";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import DeviceIcon from "assets/editor/device.png";
import { useMobile, useUserAPI } from "hooks";
import moment from "moment";
//import { GetComponentIcon } from "pbHelpers/ComponentType"; //TODO: Put this pack in for the icons once components are done
import { pond } from "protobuf-ts/pond";
import { useGlobalState } from "providers";
import { useNotificationAPI } from "providers";
import React, { useCallback, useEffect, useState } from "react";
import { useNavigate } from "react-router";

const useStyles = makeStyles((theme: Theme) => ({
    chatDrawer: {
      padding: theme.spacing(1),
      height: "100%",
      minWidth: theme.spacing(54),
      maxWidth: theme.spacing(54)
    },
    chatDrawerMobile: {
      padding: theme.spacing(1),
      height: "auto",
      width: "100%"
    },
    drawerHeader: {
      display: "flex",
      alignItems: "center",
      padding: theme.spacing(0, 1),
      // necessary for content to be below app bar
      ...theme.mixins.toolbar,
      justifyContent: "space-between"
    }
}));

interface Props {
  notificationDrawerOpen: boolean;
  setNotificationDrawerOpen: React.Dispatch<React.SetStateAction<boolean>>;
}

export default function NotificationDrawer(props: Props) {
  const { notificationDrawerOpen, setNotificationDrawerOpen } = props;

  const [loading, setLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [notifications, setNotifications] = useState<Map<string, pond.Notification>>(new Map());
  const [offset, setOffset] = useState(0);
  const [total, setTotal] = useState(9999999);

  const history = useNavigate();
  const isMobile = useMobile();
  const classes = useStyles();
  const theme = useTheme();
  const notificationAPI = useNotificationAPI();
  const userAPI = useUserAPI();
  const [{ user, as }] = useGlobalState();

  const loadNotifications = useCallback(() => {
    if (user.id().length < 1) return;
    setLoading(true);
    notificationAPI
      .listNotifications(10, 0, "desc", "timestamp", undefined, as)
      .then(resp => {
        let r = pond.ListNotificationsResponse.fromObject(resp.data);
        setTotal(r.total);
        let n: Map<string, pond.Notification> = new Map();
        r.notifications.forEach(noti => {
          n.set(noti.settings?.key ? noti.settings.key : "", noti);
        });
        setNotifications(n);
        let u = user.protobuf();
        if (u.status) {
          let DATE_RFC2822 = "ddd, DD MMM YYYY HH:mm:ss ZZ";
          u.status.lastNotificationViewed = moment()
            .locale("en")
            .format(DATE_RFC2822);
          userAPI.updateUser(user.id(), u);
        }
      })
      .finally(() => {
        setLoading(false);
      });
  }, [notificationAPI, setLoading, setNotifications, user, userAPI, as]);

  useEffect(() => {
    if (offset === 0) return;
    setLoadingMore(true);
    notificationAPI
      .listNotifications(10, offset, "desc", "timestamp", undefined, as)
      .then(resp => {
        let r = pond.ListNotificationsResponse.fromObject(resp.data);
        let n: Map<string, pond.Notification> = new Map(notifications);
        r.notifications.forEach(noti => {
          n.set(noti.settings?.key ? noti.settings.key : "", noti);
        });
        setNotifications(n);
      })
      .finally(() => {
        setLoadingMore(false);
      });
  }, [offset, notificationAPI]); // eslint-disable-line react-hooks/exhaustive-deps

  const removeNotification = (keys: string[]) => {
    notificationAPI.hideNotification(keys).then(() => {
      let n = new Map(notifications);
      keys.forEach(key => {
        n.delete(key);
      });
      setNotifications(n);
      setTotal(total - keys.length);
    });
  };

  const hasSource = (notification: pond.Notification) => {
    return Boolean(notification.settings?.sourceType && notification.settings?.sourceKey);
  };

  const notificationClick = (notification: pond.Notification) => {
    setNotificationDrawerOpen(false);
    setNotifications(new Map());
    if (!notification.settings?.sourceType) return;
    if (!notification.settings?.sourceKey) return;
    let url = "/" + notification.settings?.sourceType + "s/" + notification.settings?.sourceKey;
    history(url); //in order to update the history stack add '{ replace: true }' as a second parameter
  };

  useEffect(() => {
    if (loading) return;
    if (!notificationDrawerOpen) return;
    loadNotifications();

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [loadNotifications, notificationDrawerOpen]);

  return (
    <Drawer
      anchor="right"
      open={notificationDrawerOpen}
      onClose={() => setNotificationDrawerOpen(false)}
      style={{ height: "100%", maxWidth: "100%" }}
      title={"Notifications"}>
      <div className={isMobile ? classes.chatDrawerMobile : classes.chatDrawer}>
        <div className={classes.drawerHeader}>
          <IconButton onClick={() => setNotificationDrawerOpen(false)}>
            <ChevronRightIcon />
          </IconButton>
          <Typography style={{ fontWeight: 650, fontSize: 20 }}>Notifications</Typography>
          <Button
            variant="contained"
            color="primary"
            onClick={() => {
              removeNotification(Array.from(notifications.keys()));
            }}>
            Clear
          </Button>
        </div>
        <List>
          <Divider />
          {loading && (
            <div style={{ textAlign: "center", margin: theme.spacing(2) }}>
              <CircularProgress />
            </div>
          )}
          {!loading && notifications.size < 1 && (
            <Typography
              color="textSecondary"
              style={{ textAlign: "center", margin: theme.spacing(2) }}>
              No Notifications
            </Typography>
          )}
          {!loading &&
            [...notifications.values()].map(notification => {
              let cIcon = DeviceIcon;
              // TODO: put this back in when the component stuff has been added
              // if (notification.settings?.componentSource) {
              //   let newIcon = GetComponentIcon(
              //     notification.settings.componentSource.type,
              //     undefined,
              //     theme.palette.type
              //   );
              //   cIcon = newIcon ? newIcon : cIcon;
              // } else if (notification.settings?.logo) {
              //   cIcon = notification.settings?.logo;
              // }
              let title = notification.settings?.title
                ? notification.settings?.title
                : "Device " + notification.settings?.sourceKey;
              //notification.settings?.sourceKey
              return (
                <React.Fragment key={notification.settings?.key}>
                  <ListItem
                    // button={hasSource(notification) as any}
                    onClick={() => notificationClick(notification)}
                    >
                    <ListItemIcon>
                      {/*<ImgIcon src={cIcon} />*/}
                      <Avatar alt={user.name()} src={cIcon} />
                    </ListItemIcon>
                    <ListItemText>
                      <Grid container direction="column">
                        <Grid container direction="row" alignItems="center" alignContent="center">
                          <Grid item>
                            <Typography>{title}</Typography>
                          </Grid>
                          <Grid item>
                            <Typography
                              color={"textSecondary"}
                              style={{ marginLeft: theme.spacing(0.5) }}>
                              {notification.settings?.subtitle &&
                                " - " + notification.settings?.subtitle}
                            </Typography>
                          </Grid>
                        </Grid>
                        {notification.status?.timestamp && (
                          <Grid
                            item
                            style={{
                              marginTop: theme.spacing(-0.75),
                              marginLeft: theme.spacing(1)
                            }}>
                            <Typography variant="caption" color="textSecondary">
                              {moment(notification.status.timestamp).fromNow()}
                            </Typography>
                          </Grid>
                        )}
                        {hasSource(notification) && (
                          <Grid item>
                            <Typography variant="subtitle1" color="textSecondary">
                              Click to view {notification.settings?.sourceType}
                            </Typography>
                          </Grid>
                        )}
                      </Grid>
                    </ListItemText>
                    <ListItemSecondaryAction>
                      <Tooltip title="Hide Notification">
                        <IconButton
                          onClick={() =>
                            removeNotification(
                              notification.settings?.key ? [notification.settings.key] : []
                            )
                          }>
                          <Remove />
                        </IconButton>
                      </Tooltip>
                    </ListItemSecondaryAction>
                  </ListItem>
                  <Divider />
                </React.Fragment>
              );
            })}
          {!loading && !loadingMore && notifications.size > 0 && notifications.size < total && (
            <ListItem onClick={() => setOffset(offset + 10)}>
              <div style={{ margin: "auto" }}>
                <Typography>Load More</Typography>
              </div>
            </ListItem>
          )}{" "}
          {loadingMore && (
            <ListItem>
              <div style={{ margin: "auto" }}>
                <CircularProgress />
              </div>
            </ListItem>
          )}{" "}
          {!loadingMore && notifications.size > 0 && notifications.size >= total && (
            <ListItem>
              <div style={{ margin: "auto" }}>
                <Typography color="textSecondary">End of list.</Typography>
              </div>
            </ListItem>
          )}
        </List>
      </div>
    </Drawer>
  );
}
