import {
  Accordion,
  AccordionDetails,
  AccordionSummary,
  Box,
  Button,
  Card,
  Checkbox,
  DialogActions,
  DialogContent,
  DialogTitle,
  FormControl,
  FormControlLabel,
  FormHelperText,
  FormLabel,
  Grid2 as Grid,
  IconButton,
  InputAdornment,
  List,
  ListItem,
  ListItemIcon,
  ListItemText,
  ListSubheader,
  MenuItem,
  Select,
  TextField,
  Theme,
  Tooltip,
  Typography
} from "@mui/material";
import { ExpandMore, RemoveCircle as RemoveIcon, AddCircle as AddIcon } from "@mui/icons-material";
import ResponsiveDialog from "common/ResponsiveDialog";
import { Option } from "common/SearchSelect";
import classNames from "classnames";
import { Component, Interaction } from "models";
import moment from "moment";
import { getFriendlyName, getMeasurements } from "pbHelpers/ComponentType";
import { Measurement, Operator } from "pbHelpers/Enums";
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
import { pond } from "protobuf-ts/pond";
import { quack } from "protobuf-ts/quack";
import { useGlobalState, useInteractionsAPI, useSnackbar } from "providers";
import { useNotificationAPI } from "providers/pond/notificationAPI";
import React, { useEffect, useState } from "react";
import { capitalize, cloneDeep } from "lodash";
import { timeOfDayDescriptor } from "pbHelpers/Interaction";
import { TimePicker } from "@mui/x-date-pickers";
import { getThemeType } from "theme/themeType";
import { green, red } from "@mui/material/colors";
import { makeStyles } from "@mui/styles";



interface Props {
  linkedComponents: Map<string, Component>;
  componentDevices: Map<string, number>;
  objectType: pond.ObjectType;
  objectKey: string;
}

interface Alert {
  conditions: pond.InteractionCondition[];
  components: Component[];
}

const useStyles = makeStyles((theme: Theme) => {
  return ({
    borderedContainer: {
      padding: theme.spacing(1),
      marginBottom: theme.spacing(2),
      border: "1px solid rgba(255, 255, 255, 0.12)",
      borderRadius: "4px"
    },
    greenButton: {
      color: green["600"]
    },
    redButton: {
      color: red["600"]
    },
    noPadding: {
      padding: 0
    },
    timeRange: {
      fontSize: "0.875em",
      marginTop: "20px"
    },
    dark: {
      backgroundColor: getThemeType() === "light" ? "rgb(245, 245, 245)" : "rgb(50, 50, 50)",
      padding: 5
    },
    light: {
      backgroundColor: getThemeType() === "light" ? "rgb(235, 235, 235)" : "rgb(60, 60, 60)",
      padding: 5
    }
  });
});

export default function ObjectAlerts(props: Props) {
  const { linkedComponents, componentDevices, objectKey, objectType } = props;
  const classes = useStyles();
  const { openSnack } = useSnackbar();
  const [{ as }] = useGlobalState();
  const interactionsAPI = useInteractionsAPI();
  const [interactions, setInteractions] = useState<Interaction[]>([]);
  const [typeOptions, setTypeOptions] = useState<Option[]>([]);
  const [alerts, setAlerts] = useState<Alert[]>([]);
  //the interaction key to the component it is set on
  const [interactionComponent, setInteractionComponent] = useState<Map<string, string>>(new Map());

  //state variables for notifications
  const notificationAPI = useNotificationAPI();
  const [recentNotifications, setRecentNotifications] = useState<pond.Notification[]>([]);
  const [notificationsLoading, setNotificationsLoading] = useState(false);
  const [totalNotifications, setTotalNotifications] = useState(0);

  //stat variables for adding new alerts
  const [newAlertOpen, setNewAlertOpen] = useState(false);
  const [selectedAlertComponents, setSelectedAlertComponents] = useState<string[]>([]);
  const [newAlertComponentType, setNewAlertComponentType] = useState<quack.ComponentType>(
    quack.ComponentType.COMPONENT_TYPE_INVALID
  );
  const [conditions, setConditions] = useState<pond.InteractionCondition[]>([]);
  const [nodeOptions, setNodeOptions] = useState<JSX.Element[]>([]);
  const [subtypeDropdown, setSubtypeDropdown] = useState<number>(0);
  //condition value strings - so that decimals are easier to type into the field
  const [valStrings, setValStrings] = useState(["0", "0"]);
  //the nodes for the subnode interactions
  const [nodeOne, setNodeOne] = useState(0);
  const [nodeTwo, setNodeTwo] = useState(0);

  //schedule variables
  const [schedule, setSchedule] = useState(
    pond.InteractionSchedule.create({
      weekdays: ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]
    })
  );

  useEffect(() => {
    //loop through the linked components to get each of their interactions
    //TODO-CS: consider making an api function to get the interactions for multiple components, possibly based off objects, in one call,
    //to get all interactions for bin components this would solve the issue of making multiple calls as well as not having to use async await
    let newInteractions: Interaction[] = [];
    let icMap: Map<string, string> = new Map();
    let includedOps: quack.ComponentType[] = [];
    let typeOps: Option[] = [];
    let index = 0;
    //use async to make sure to wait for the response from the api call and have the interactions set before going to get the next one
    //this prevents seperate responses from assigning to the array without knowing about interactions from those seperate responses
    //for example: without async two responses come back at the same time, one has two interactions and another has one but, neither have put their interactions
    //into the array yet so they both reference an empty array, the first response puts its two into an empty array and sets it but then the next one also puts
    //its response into an empty array as well and sets it causing the first two to be lost
    linkedComponents.forEach(async (comp, key) => {
      index++;
      //get the interactions for the component
      let device = componentDevices.get(key);
      if (device !== undefined) {
        await interactionsAPI.listInteractionsByComponent(device, comp.location(), undefined, as).then(resp => {
          if (resp.length > 0) {
            resp.forEach(interaction => {
              icMap.set(interaction.key(), key);
            });
            newInteractions = newInteractions.concat(resp);
          }
        });
      }
      //set the state variables if it is the last one in the list
      if (index === linkedComponents.size) {
        setInteractionComponent(icMap);
        setInteractions([...newInteractions]);
      }
      //use the component type to the type options if it is not already present
      if (!includedOps.includes(comp.type())) {
        includedOps.push(comp.type());
        typeOps.push({
          label: getFriendlyName(comp.type()),
          value: comp.type()
        });
      }
    });
    setTypeOptions(typeOps);
  }, [linkedComponents, interactionsAPI, componentDevices]);

  const matchConditions = (interaction: Interaction, alert: Alert) => {
    //if the number of conditions are not the same they are different
    if (interaction.settings.conditions.length !== alert.conditions.length) {
      return false;
    }
    //continure with the comparison
    let matching = true;
    interaction.settings.conditions.forEach((condition, i) => {
      if (
        condition.comparison !== alert.conditions[i].comparison ||
        condition.measurementType !== alert.conditions[i].measurementType ||
        condition.value !== alert.conditions[i].value
      ) {
        matching = false;
      }
    });
    return matching;
  };

  //build the alerts to display
  useEffect(() => {
    //loop through the interactions
    let currentAlerts: Alert[] = [];
    interactions.forEach(interaction => {
      //if the interaction sends notifications
      if (interaction.settings.notifications && interaction.settings.notifications.notify) {
        //determine if the interaction already has an alert in the alerts array
        let similarAlert: number = -1;
        currentAlerts.forEach((alert, i) => {
          if (matchConditions(interaction, alert)) {
            similarAlert = i;
          }
        });

        //if no current alert matched the conditions add a new alert to the array
        let compKey = interactionComponent.get(interaction.key());
        if (compKey) {
          let component = linkedComponents.get(compKey);
          if (component) {
            if (similarAlert === -1) {
              let newAlert: Alert = {
                conditions: interaction.settings.conditions,
                components: [component]
              };
              currentAlerts.push(newAlert);
            } else {
              currentAlerts[similarAlert].components.push(component);
            }
          }
        }
      }
    });
    setAlerts(currentAlerts);
  }, [interactions, interactionComponent, linkedComponents]);

  //get the notifications for the components on an object
  useEffect(() => {
    if (notificationsLoading) return;
    setNotificationsLoading(true);
    notificationAPI
      .listObjectNotifications(objectKey, objectType, 10, 0, undefined, undefined, undefined, as)
      .then(resp => {
        setRecentNotifications(resp.data.notifications);
        setTotalNotifications(resp.data.total);
      })
      .catch(_err => {})
      .finally(() => {
        setNotificationsLoading(false);
      });
  }, [objectKey, objectType, notificationAPI]); //eslint-disable-line react-hooks/exhaustive-deps

  //use the selected components to determine the lowest amount of nodes for the options
  useEffect(() => {
    setNodeOne(0);
    setNodeTwo(0);
    setSubtypeDropdown(0);
    let nodeCount = 12; //start with the maximum number of nodes for a cable
    linkedComponents.forEach(comp => {
      if (selectedAlertComponents.includes(comp.key())) {
        if (comp.lastMeasurement[0] && comp.lastMeasurement[0].values[0]) {
          let nodes = comp.lastMeasurement[0].values[0].values.length;
          nodeCount = nodes < nodeCount ? nodes : nodeCount;
        }
      }
    });
    let options = [];
    for (let i = 0; i <= nodeCount; i++) {
      options.push(
        <MenuItem key={i} value={i}>
          {i === 0 ? "None" : "Node " + i}
        </MenuItem>
      );
    }
    setNodeOptions(options);
  }, [linkedComponents, selectedAlertComponents]);

  const loadMoreNotifications = () => {
    console.log("load more");
    let current = recentNotifications;
    setNotificationsLoading(true);
    notificationAPI
      .listObjectNotifications(
        objectKey,
        objectType,
        10,
        current.length,
        undefined,
        undefined,
        undefined,
        as
      )
      .then(resp => {
        if (resp.data.notifications.length > 0) {
          let c = current.concat(resp.data.notifications);
          setRecentNotifications([...c]);
        }
      })
      .catch(_err => {})
      .finally(() => {
        setNotificationsLoading(false);
      });
  };

  const readableCondition = (condition: pond.InteractionCondition) => {
    let describer = describeMeasurement(condition.measurementType);
    let type = describer.label();
    let comparison =
      condition.comparison === quack.RelationalOperator.RELATIONAL_OPERATOR_EQUAL_TO
        ? "Exactly"
        : condition.comparison === quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN
        ? "Above"
        : "Below";
    let value = describer.toDisplay(condition.value);
    return (
      <Box>
        <Typography>{type + " " + comparison + " " + value + describer.GetUnit()}</Typography>
      </Box>
    );
  };

  const alertAccordion = (alert: Alert) => {
    return (
      <Accordion style={{ width: "100%" }}>
        <AccordionSummary expandIcon={<ExpandMore />}>
          <Grid container direction="column">
            {alert.conditions.map((condition, i) => (
              <Grid key={i}>
                {readableCondition(condition)}
              </Grid>
            ))}
          </Grid>
        </AccordionSummary>
        <AccordionDetails>
          <List>
            <ListSubheader>Reporting Components</ListSubheader>
            {alert.components.map((comp, i) => (
              <ListItem key={i}>{comp.name()}</ListItem>
            ))}
          </List>
        </AccordionDetails>
      </Accordion>
    );
  };

  const addInteractionToComponents = () => {
    //array of device and component ids ie, [4:9-5-12, 4:9-5-13, 3:9-5-12]
    let compIds: string[] = [];
    selectedAlertComponents.forEach(comp => {
      let devID = componentDevices.get(comp);
      let component = linkedComponents.get(comp);
      if (devID && component) {
        compIds.push(devID + ":" + component.locationString());
      }
    });
    let newAlert = pond.InteractionSettings.create();
    newAlert.conditions = conditions;
    newAlert.instance = 1;
    newAlert.schedule = schedule;
    newAlert.subtype = Interaction.create().subtypeFromNodes(nodeOne, nodeTwo);
    newAlert.result = pond.InteractionResult.create({
      type: quack.InteractionResultType.INTERACTION_RESULT_TYPE_REPORT
    });
    newAlert.notifications = pond.InteractionNotifications.create({
      notify: true
    });
    interactionsAPI
      .addInteractionToComponents(compIds, newAlert, as)
      .then(_resp => {
        openSnack("interaction added to selected components");
      })
      .catch(_err => {
        openSnack("there was a problem adding the interaction to the selected components");
      });
    setNewAlertOpen(false);
  };

  //display the components that match the type that was selected for the new alert
  const listMatchingComponents = () => {
    let matching: Component[] = [];
    linkedComponents.forEach(comp => {
      if (comp.type() === newAlertComponentType) {
        matching.push(comp);
      }
    });
    return (
      <List>
        {matching.map(comp => (
          <ListItem key={comp.key()}>
            <ListItemIcon>
              <Checkbox
                checked={selectedAlertComponents.includes(comp.key())}
                onChange={(_, checked) => {
                  let selected = selectedAlertComponents;
                  if (checked) {
                    selected.push(comp.key());
                  } else {
                    selected.splice(selected.indexOf(comp.key()), 1);
                  }
                  setSelectedAlertComponents([...selected]);
                }}
              />
            </ListItemIcon>
            <ListItemText>{comp.name()}</ListItemText>
          </ListItem>
        ))}
      </List>
    );
  };

  const availableMeasurementTypes = (type: quack.ComponentType): quack.MeasurementType[] => {
    return getMeasurements(type).map(m => m.measurementType);
  };

  const initialConditions = (type: quack.ComponentType): pond.InteractionCondition[] => {
    let measurementType = availableMeasurementTypes(type)[0];
    let condition = pond.InteractionCondition.create({
      measurementType: measurementType,
      comparison: measurementType === Measurement.boolean ? Operator.equals : Operator.less,
      value: 0
    });
    return [condition];
  };

  const measurementTypeMenuItems = () => {
    return availableMeasurementTypes(newAlertComponentType).map(measurementType => (
      <MenuItem key={measurementType} value={measurementType}>
        {describeMeasurement(measurementType).label()}
      </MenuItem>
    ));
  };

  const changeCondition = (newCondition: pond.InteractionCondition, index: number) => {
    let c = conditions;
    c[index] = newCondition;
    setConditions([...c]);
  };

  const conditionGroup = (condition: pond.InteractionCondition, index: number) => {
    let measurementType = condition.measurementType;
    let describer = describeMeasurement(measurementType, newAlertComponentType);
    let isBoolean = condition.measurementType === Measurement.boolean;
    return (
      <React.Fragment key={index}>
        <Grid
          key={"interaction"}
          container
          direction="row"
          alignItems="center"
          spacing={2}>
          {index > 0 && (
            <Grid size={12}>
              <Typography align="center">AND</Typography>
            </Grid>
          )}
          <Grid size={{ xs:10, sm:4 }}>
            <TextField
              select
              id="measurementType"
              required={true}
              label=""
              helperText="Measurement"
              //error={!isMeasurementTypeValid(interaction.settings.conditions[index].measurementType)}
              //disabled={!isSourceValid(interaction.settings.source) || !canEdit}
              value={condition.measurementType}
              onChange={event => {
                condition.measurementType = +event.target.value;
                changeCondition(condition, index);
              }}
              autoFocus={false}
              margin="dense"
              variant="standard"
              fullWidth
              InputLabelProps={{ shrink: true }}>
              {measurementTypeMenuItems()}
            </TextField>
          </Grid>
          <Grid size={{ xs:10, sm:3 }}>
            <TextField
              select
              id="comparison"
              required={true}
              label=""
              helperText="Comparator"
              //disabled={!isSourceValid(interaction.settings.source) || isBoolean || !canEdit}
              value={condition.comparison}
              onChange={event => {
                condition.comparison = +event.target.value;
                changeCondition(condition, index);
              }}
              autoFocus={false}
              margin="dense"
              variant="standard"
              fullWidth
              InputLabelProps={{ shrink: true }}>
              {!isBoolean && [
                <MenuItem key={2} value={Operator.less}>
                  {"is below"}
                </MenuItem>,
                <MenuItem key={3} value={Operator.greater}>
                  {"is above"}
                </MenuItem>
              ]}
              <MenuItem key={1} value={Operator.equals}>
                {"is exactly"}
              </MenuItem>
            </TextField>
          </Grid>
          <Grid size={{xs:8, sm:4}}>
            <TextField
              select={isBoolean}
              id="value"
              required={true}
              type={"text"}
              label=""
              helperText="Value"
              error={isNaN(+valStrings[index])}
              value={valStrings[index]}
              onChange={event => {
                let strings = valStrings;
                strings[index] = event.target.value;
                setValStrings([...strings]);
                if (!isNaN(+valStrings[index])) {
                  condition.value = describer.toStored(+event.target.value);
                  changeCondition(condition, index);
                }
              }}
              autoFocus={false}
              margin="dense"
              variant="standard"
              fullWidth
              InputProps={{
                endAdornment: <InputAdornment position="end">{describer.unit()}</InputAdornment>
              }}
              InputLabelProps={{ shrink: true }}>
              {isBoolean && [
                <MenuItem key={0} value={0}>
                  {describer.enumerations()[0]}
                </MenuItem>,
                <MenuItem key={1} value={1}>
                  {describer.enumerations()[1]}
                </MenuItem>
              ]}
            </TextField>
          </Grid>
          <Grid size={{xs:2, sm:1}}>
            {index === 0 ? (
              <Tooltip title="Add another condition">
                <IconButton
                  color="primary"
                  disabled={conditions.length > 1}
                  aria-label="Add another condition"
                  onClick={() => {
                    let c = cloneDeep(conditions);
                    let newConditions = c.concat(initialConditions(newAlertComponentType));
                    setConditions(newConditions);
                  }}
                  className={classNames(classes.greenButton, classes.noPadding)}>
                  <AddIcon />
                </IconButton>
              </Tooltip>
            ) : (
              <Tooltip title="Remove this condition">
                <IconButton
                  color="default"
                  //disabled={!canEdit}
                  aria-label="Remove condition"
                  onClick={() => {
                    let c = conditions;
                    c.splice(index, 1);
                    setConditions([...c]);
                  }}
                  className={classNames(classes.redButton, classes.noPadding)}>
                  <RemoveIcon />
                </IconButton>
              </Tooltip>
            )}
          </Grid>
        </Grid>
        {nodeOptions.length > 2 && (
          <Grid
            key={"nodes"}
            container
            direction="row"
            alignItems="center"
            spacing={2}>
            <Grid size={{xs:10, sm:4}}>
              <TextField
                select
                id="subtype"
                label="Subtype"
                //disabled={!isSourceValid(interaction.settings.source) || !canEdit}
                value={subtypeDropdown}
                onChange={event => {
                  setSubtypeDropdown(+event.target.value);
                }}
                margin="dense"
                variant="standard"
                fullWidth
                InputLabelProps={{ shrink: true }}>
                <MenuItem key={0} value={0}>
                  Any
                </MenuItem>
                <MenuItem key={1} value={1}>
                  Average
                </MenuItem>
                <MenuItem key={2} value={2}>
                  Single Node
                </MenuItem>
                <MenuItem key={3} value={3}>
                  Node Diff
                </MenuItem>
                <MenuItem key={4} value={4}>
                  Up To
                </MenuItem>
              </TextField>
            </Grid>
            <Grid size={{xs:10, sm:4}}>
              {(subtypeDropdown === 2 || subtypeDropdown === 3 || subtypeDropdown === 4) && (
                <TextField
                  select
                  id="interactionType"
                  label="Node 1"
                  //disabled={!isSourceValid(interaction.settings.source) || !canEdit}
                  value={nodeOne}
                  onChange={event => {
                    setNodeOne(+event.target.value);
                  }}
                  margin="dense"
                  variant="standard"
                  fullWidth
                  InputLabelProps={{ shrink: true }}>
                  {nodeOptions}
                </TextField>
              )}
            </Grid>
            <Grid size={{xs:10, sm:4}}>
              {subtypeDropdown === 3 && (
                <TextField
                  select
                  id="interactionType"
                  label="Node 2"
                  //disabled={!isSourceValid(interaction.settings.source) || !canEdit}
                  value={nodeTwo}
                  onChange={event => {
                    setNodeTwo(+event.target.value);
                  }}
                  margin="dense"
                  variant="standard"
                  fullWidth
                  InputLabelProps={{ shrink: true }}>
                  {nodeOptions}
                </TextField>
              )}
            </Grid>
          </Grid>
        )}
      </React.Fragment>
    );
  };

  const conditionInput = () => {
    // const conditionGroups: JSX.Element[] = [];
    // for (let i = 0; i < conditions.length; i++) {
    //   conditionGroups[i] = conditionGroup(i);
    // }
    return (
      <FormControl
        component={"fieldset" as "div"}
        className={classes.borderedContainer}
        fullWidth
        disabled={selectedAlertComponents.length === 0}>
        <FormLabel component={"legend" as "caption"}>Conditions</FormLabel>
        {selectedAlertComponents.length > 0 ? (
          <React.Fragment>
            {conditions.map((condition, i) => conditionGroup(condition, i))}
          </React.Fragment>
        ) : (
          <FormHelperText>You must select a source before adding conditions</FormHelperText>
        )}
      </FormControl>
    );
  };

  const setScheduleTime = (id: string, event: any) => {
    let updatedSchedule = cloneDeep(schedule);
    if (id === "shortcut") {
      let value = event.target.value;
      if (value === "allDay") {
        updatedSchedule.timeOfDayStart = "00:00";
        updatedSchedule.timeOfDayEnd = "24:00";
      } else if (value === "before") {
        updatedSchedule.timeOfDayStart = "00:00";
        if (!updatedSchedule.timeOfDayEnd || updatedSchedule.timeOfDayEnd === "24:00") {
          updatedSchedule.timeOfDayEnd = "23:59";
        }
      } else if (value === "after") {
        updatedSchedule.timeOfDayEnd = "24:00";
        if (updatedSchedule.timeOfDayStart === "00:00") {
          updatedSchedule.timeOfDayStart = "00:01";
        }
      } else {
        if (updatedSchedule.timeOfDayStart === "00:00") {
          updatedSchedule.timeOfDayStart = "00:01";
        }
        if (updatedSchedule.timeOfDayEnd === "24:00") {
          updatedSchedule.timeOfDayEnd = "23:59";
        }
      }
    } else {
      let timeOfDay =
        event
          .hour()
          .toString()
          .padStart(2, "0") +
        ":" +
        event
          .minute()
          .toString()
          .padStart(2, "0");
      if (id === "start") {
        updatedSchedule.timeOfDayStart = timeOfDay;
      } else if (id === "end") {
        if (timeOfDay === "00:00") {
          timeOfDay = "24:00";
        }
        updatedSchedule.timeOfDayEnd = timeOfDay;
      }
    }
    updatedSchedule.timezone = moment.tz.guess();
    setSchedule(updatedSchedule);
  };

  const toggleDaySelected = (day: string, event: any) => {
    let updatedSchedule = cloneDeep(schedule);
    if (event.target.checked) {
      if (!updatedSchedule.weekdays.includes(day)) {
        updatedSchedule.weekdays.push(day);
      }
    } else {
      updatedSchedule.weekdays.splice(updatedSchedule.weekdays.indexOf(day), 1);
    }
    setSchedule(updatedSchedule);
  };

  const daySelector = (day: string, size: any) => {
    //const schedule = or(interaction.settings.schedule, pond.InteractionSchedule.create());
    return (
      <Grid container size={{xs: size, sm:1}} alignItems="center">
        <FormControlLabel
          control={
            <Checkbox
              id={day}
              checked={schedule.weekdays.includes(day)}
              onChange={event => toggleDaySelected(day, event)}
              value={day}
              color="secondary"
            />
          }
          label={capitalize(day.substr(0, 2))}
          labelPlacement="bottom"
        />
      </Grid>
    );
  };

  const scheduler = () => {
    //let schedule = pond.InteractionSchedule.create();
    let timezone = moment.tz.guess();
    let todStart = "00:00".split(":");
    let todEnd = "23:59".split(":");
    let start = moment
      .tz(timezone)
      .startOf("day")
      .add(todStart[0], "hours")
      .add(todStart[1], "minutes")
      .local();
    let end = moment
      .tz(timezone)
      .startOf("day")
      .add(todEnd[0], "hours")
      .add(todEnd[1], "minutes")
      .local();
    let descriptor = timeOfDayDescriptor(schedule);
    let showStart = descriptor === "after" || descriptor === "from";
    let showEnd = descriptor === "before" || descriptor === "from";
    let showBoth = showStart && showEnd;
    return (
      <FormControl component={"fieldset" as "div"} className={classes.borderedContainer} fullWidth>
        <FormLabel component={"legend" as "caption"}>Schedule</FormLabel>
        <Grid container direction="row" spacing={0}>
          {daySelector("sunday", 3)}
          {daySelector("monday", 3)}
          {daySelector("tuesday", 3)}
          {daySelector("wednesday", 3)}
          {daySelector("thursday", 4)}
          {daySelector("friday", 4)}
          {daySelector("saturday", 4)}
        </Grid>
        <Grid container direction="row" spacing={2} alignItems="center">
          <Grid size={{xs:12, sm:3}}>
            <TextField
              select
              id="timeOfDayShortcut"
              value={descriptor}
              onChange={(event: any) => setScheduleTime("shortcut", event)}
              fullWidth
              autoFocus={false}
              margin="normal"
              variant="standard"
              InputLabelProps={{ shrink: true }}>
              <MenuItem key="allDay" value="allDay">
                All Day
              </MenuItem>
              <MenuItem key="before" value="before">
                Before
              </MenuItem>
              <MenuItem key="after" value="after">
                After
              </MenuItem>
              <MenuItem key="from" value="from">
                From
              </MenuItem>
            </TextField>
          </Grid>
          {showStart && (
            <Grid size={{xs:5, sm:3}}>
              <TimePicker
                //renderInput={props => <TextField {...props} helperText="" />}
                value={start}
                onChange={(event: any) => setScheduleTime("start", event)}
              />
            </Grid>
          )}
          {showBoth && (
            <Grid size={{xs:2,sm:1}}>
              <Typography
                variant="subtitle1"
                color="textSecondary"
                className={classes.timeRange}
                align="right">
                to
              </Typography>
            </Grid>
          )}
          {showEnd && (
            <Grid size={{xs:5, sm:3}}>
              <TimePicker
                //renderInput={props => <TextField {...props} helperText="" />}
                value={end}
                onChange={(event: any) => setScheduleTime("end", event)}
              />
            </Grid>
          )}
        </Grid>
      </FormControl>
    );
  };

  const newAlertDialog = () => {
    return (
      <ResponsiveDialog
        open={newAlertOpen}
        onClose={() => {
          setNewAlertOpen(false);
        }}>
        <DialogTitle>Set New Alert</DialogTitle>
        <DialogContent>
          {/* Dropdown to select the component type to add the interaction to */}
          <Select
            id="componentType"
            label="Component Type"
            fullWidth
            displayEmpty
            value={newAlertComponentType}
            onChange={e => {
              setNewAlertComponentType(e.target.value as quack.ComponentType);
              setSelectedAlertComponents([]);
              setConditions(initialConditions(e.target.value as quack.ComponentType));
            }}>
            <MenuItem key={0} value={0}>
              Select Component Type
            </MenuItem>
            {typeOptions.map(option => (
              <MenuItem key={option.value} value={option.value}>
                {option.label}
              </MenuItem>
            ))}
          </Select>
          {/* list of checkboxes for the components that match that type */}
          {listMatchingComponents()}
          {/* have the conditions set here */}
          {conditionInput()}
          {/* have the schedule set here */}
          {scheduler()}
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setNewAlertOpen(false)} variant="contained">
            Cancel
          </Button>
          <Button
            disabled={selectedAlertComponents.length === 0}
            onClick={addInteractionToComponents}
            variant="contained"
            color="primary">
            Confirm
          </Button>
        </DialogActions>
      </ResponsiveDialog>
    );
  };

  const alertDisplay = () => {
    return (
      <List style={{ margin: 5 }}>
        <ListSubheader>Alerts</ListSubheader>
        {alerts.map((alert, i) => (
          <ListItem key={i}>{alertAccordion(alert)}</ListItem>
        ))}
      </List>
    );
  };

  const notificationList = () => {
    return (
      <List style={{ margin: 5 }}>
        <ListSubheader>Notifications</ListSubheader>
        {recentNotifications && (
          <React.Fragment>
            {recentNotifications.map((notification, i) => (
              <ListItem key={i} className={i % 2 === 0 ? classes.dark : classes.light}>
                <Typography style={{ fontWeight: 650 }}>
                  {moment(notification.status?.timestamp).format("MMMM DD, YYYY - h:mm a")}
                </Typography>{" "}
                :{" "}
                <Typography>
                  {notification.settings?.title + " - " + notification.settings?.subtitle}
                </Typography>
              </ListItem>
            ))}
            {recentNotifications.length < totalNotifications && (
              <ListItem key={"button"}>
                <Button onClick={loadMoreNotifications} disabled={notificationsLoading}>
                  Get More
                </Button>
              </ListItem>
            )}
          </React.Fragment>
        )}
      </List>
    );
  };

  return (
    <Card raised style={{ margin: 5 }}>
      <Box padding={1} display="flex" justifyContent="space-between">
        <Typography style={{ fontWeight: 650, fontSize: 25 }}>Alerts & Notifications</Typography>
        <Button
          variant="contained"
          color="primary"
          onClick={() => {
            setNewAlertOpen(true);
          }}>
          New Alert
        </Button>
      </Box>
      {alertDisplay()}
      {notificationList()}
      {newAlertDialog()}
    </Card>
  );
}
