import { 
  AccountBox, 
  Close, 
  ExpandLess, 
  ExpandMore, 
  Face, 
  Share as ShareIcon, 
  Notifications as NotificationsIcon, 
  Email as EmailIcon,
  Textsms as TextIcon,
} from "@mui/icons-material";
import { AppBar, Box, Button, Checkbox, CircularProgress, Collapse, Divider, FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel, Grid2, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Radio, RadioGroup, TextField, Theme, Toolbar, Tooltip, Typography } from "@mui/material";
import ResponsiveDialog from "common/ResponsiveDialog";
import UserAvatar from "./UserAvatar";
import { useGlobalState, useUserAPI } from "providers";
import { useEffect, useState } from "react";
import { makeStyles } from "@mui/styles";
import { blue } from "@mui/material/colors";
import ShareObject from "./ShareObject";
import { pond } from "protobuf-ts/pond";
import { User, userScope } from "models";
import SearchSelect from "common/SearchSelect";
import {Option as OptionType} from "common/SearchSelect";
import moment from "moment";
import { IconPicker } from "common/IconPicker";
import { MuiTelInput } from "mui-tel-input";

const useStyles = makeStyles((theme: Theme) => {
  return ({
    title: {
      marginLeft: theme.spacing(2),
      marginRight: theme.spacing(2),
      flex: 1
    },
    checkboxIcon: {
      minWidth: theme.spacing(5),
      [theme.breakpoints.up("sm")]: {
        minWidth: theme.spacing(6)
      },
      [theme.breakpoints.up("md")]: {
        minWidth: theme.spacing(7)
      }
    },
    shareIcon: {
      color: blue["600"],
      "&:hover": {
        color: blue["700"]
      }
    },
    iconButton: {
      margin: theme.spacing(1),
      position: "absolute",
      right: theme.spacing(6)
    }
  });
});

interface Props {
  isOpen: boolean;
  closeDialogCallback: () => void;
}

export default function UserSettings(props: Props) {
  const { isOpen, closeDialogCallback } = props;
  const [globalState, dispatch] = useGlobalState()
  const [sharing, setSharing] = useState(false)
  const userAPI = useUserAPI();
  const classes = useStyles()

  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [user, setUser] = useState<User>(globalState.user);
  const [profileExpanded, setProfileExpanded] = useState<boolean>(false);
  const [avatarExpanded, setAvatarExpanded] = useState<boolean>(false);
  const [notificationsExpanded, setNotificationsExpanded] = useState<boolean>(false);
  const [avatarUrl, setAvatarUrl] = useState<string>("");

  useEffect(() => {
    function changeIcon(icon: string | undefined) {
      let updatedUser = User.clone(user);
      updatedUser.settings.avatar = icon ? icon : user.settings.avatar;
      setUser(updatedUser);
    }
    if (avatarUrl === "") {
      changeIcon(undefined);
    } else {
      changeIcon(avatarUrl);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [avatarUrl]);

  const submit = () => {
    userAPI
      .updateUser(user.id(), user.protobuf())
      .then(() => {
        dispatch({ key: "user", value: user });
        // success("User settings successfully updated!");
        // setTemperatureUnit(user.settings.temperatureUnit);
        // setPressureUnit(user.settings.pressureUnit);
        // setDistanceUnit(user.settings.distanceUnit);
        // setGrainUnit(user.settings.grainUnit);
      })
      .catch((error: any) => {
        error("Error occurred while updating your profile");
      })
      .finally(() => {
        setIsLoading(false);
        closeDialogCallback();
      });
  };

  const setDefaultState = () => {
    setIsLoading(false);
    setUser(globalState.user);
  };

  const closeDialog = () => {
    setDefaultState();
    closeDialogCallback();
  };

  const loading = () => {
    return <CircularProgress variant="indeterminate" color="primary" />;
  };

  const changeName = (name: string) => {
    let updatedUser = User.clone(user);
    updatedUser.settings.name = name;
    setUser(updatedUser);
  };

  const changeTimezone = (tz: string) => {
    let updatedUser = User.clone(user);
    updatedUser.settings.timezone = tz;
    setUser(updatedUser);
  };

  const changePhoneNumber = (newPhoneNumber: string) => {
    let updatedUser = User.clone(user);
    updatedUser.settings.phoneNumber = newPhoneNumber;
    setUser(updatedUser);
  };

  const generalSettings = () => {
    const { name, email, phoneNumber, timezone } = user.settings;

    return (
      <Grid2 container direction="column" spacing={4} justifyContent="flex-start" alignItems="flex-start">
        <ShareObject
          scope={userScope(user.id())}
          label={""}
          permissions={[
            pond.Permission.PERMISSION_READ,
            pond.Permission.PERMISSION_SHARE,
            pond.Permission.PERMISSION_USERS,
            pond.Permission.PERMISSION_WRITE
          ]}
          isDialogOpen={sharing}
          closeDialogCallback={() => setSharing(false)}
        />
        <Tooltip title={"Share control of profile with another user"}>
          <IconButton
            aria-label="Share"
            className={classes.iconButton}
            onClick={() => setSharing(true)}>
            <ShareIcon className={classes.shareIcon} />
          </IconButton>
        </Tooltip>
        <Grid2>
          <TextField
            label="Preferred Name"
            fullWidth
            value={name}
            helperText={"Email: " + email}
            onChange={event => changeName(event.target.value.toString())}
          />
        </Grid2>
        <Grid2>
          <FormControl component="fieldset">
            <FormLabel component="legend" htmlFor="phone-number-input">
              Phone Number
            </FormLabel>
            <MuiTelInput value={phoneNumber} onChange={changePhoneNumber} />
          </FormControl>
        </Grid2>
        <Grid2 size={{ xs: 12 }}>
          <Box>
            <SearchSelect
              label="Timezone"
              selected={{ label: timezone, value: timezone } as OptionType}
              options={moment.tz.names().map(tz => ({ label: tz, value: tz } as OptionType))}
              changeSelection={(selected: OptionType | null) =>
                changeTimezone(selected ? selected.value : "")
              }
            />
          </Box>
        </Grid2>
      </Grid2>
    );
  };

  const handleChangeNotifyByDefault = (notifyByDefault: boolean) => {
    let updatedUser = User.clone(user);
    updatedUser.settings.notifyByDefault = notifyByDefault;
    setUser(updatedUser);
  };

  const handleNotificationMethod = (
    checked: boolean,
    notificationMethod: pond.NotificationMethod
  ) => {
    let updatedUser = User.clone(user);
    let notificationMethods = updatedUser.settings.notificationMethods;
    if (checked) {
      if (!notificationMethods.includes(notificationMethod)) {
        notificationMethods.push(notificationMethod);
      }
    } else {
      notificationMethods = notificationMethods.filter(element => element !== notificationMethod);
    }
    updatedUser.settings.notificationMethods = notificationMethods;
    setUser(updatedUser);
  };

  const notificationsSettings = () => {
    const { notifyByDefault, notificationMethods } = user.settings;

    return (
      <Grid2 container direction="column" spacing={4} justifyContent="flex-start" alignItems="flex-start">
        <Grid2>
          <FormControl component="fieldset">
            <FormLabel component="legend">Notification Preference</FormLabel>
            <RadioGroup
              aria-label="notification-default"
              name="notificationDefault"
              value={notifyByDefault}
              onChange={event => handleChangeNotifyByDefault(event.target.value === "true")}>
              <FormControlLabel value={true} control={<Radio />} label="Opt-in" />
              <FormControlLabel value={false} control={<Radio />} label="Opt-out" />
            </RadioGroup>
            <FormHelperText>
              {notifyByDefault
                ? "Notifications are enabled by default"
                : "Notifications are disabled by default"}
            </FormHelperText>
          </FormControl>
        </Grid2>
        <Grid2>
          <FormControl component="fieldset">
            <FormLabel component="legend">Notification Methods</FormLabel>
            <FormGroup>
              <FormControlLabel
                control={
                  <Checkbox
                    onChange={(_event, checked) =>
                      handleNotificationMethod(
                        checked,
                        pond.NotificationMethod.NOTIFICATION_METHOD_EMAIL
                      )
                    }
                    checked={
                      notificationMethods
                        ? notificationMethods.includes(
                            pond.NotificationMethod.NOTIFICATION_METHOD_EMAIL
                          )
                        : false
                    }
                  />
                }
                label={
                  <ListItem dense disableGutters>
                    <ListItemIcon className={classes.checkboxIcon}>
                      <EmailIcon />
                    </ListItemIcon>
                    <ListItemText primary="Email" />
                  </ListItem>
                }
              />

              <FormControlLabel
                control={
                  <Checkbox
                    onChange={(_event, checked) =>
                      handleNotificationMethod(
                        checked,
                        pond.NotificationMethod.NOTIFICATION_METHOD_TEXT
                      )
                    }
                    checked={
                      notificationMethods
                        ? notificationMethods.includes(
                            pond.NotificationMethod.NOTIFICATION_METHOD_TEXT
                          )
                        : false
                    }
                  />
                }
                label={
                  <ListItem dense disableGutters>
                    <ListItemIcon className={classes.checkboxIcon}>
                      <TextIcon />
                    </ListItemIcon>
                    <ListItemText
                      primary="Text Message (SMS)"
                      secondary="Requires a valid phone number"
                      secondaryTypographyProps={{ variant: "caption" }}
                    />
                  </ListItem>
                }
              />

              <FormControlLabel
                control={
                  <Checkbox
                    onChange={(_event, checked) =>
                      handleNotificationMethod(
                        checked,
                        pond.NotificationMethod.NOTIFICATION_METHOD_APP
                      )
                    }
                    checked={
                      notificationMethods
                        ? notificationMethods.includes(
                            pond.NotificationMethod.NOTIFICATION_METHOD_APP
                          )
                        : false
                    }
                  />
                }
                label={
                  <ListItem dense disableGutters>
                    <ListItemIcon className={classes.checkboxIcon}>
                      <TextIcon />
                    </ListItemIcon>
                    <ListItemText
                      primary="In-App Notifications"
                      secondary="No email or phone number required"
                      secondaryTypographyProps={{ variant: "caption" }}
                    />
                  </ListItem>
                }
              />
            </FormGroup>
          </FormControl>
        </Grid2>
      </Grid2>
    );
  };

  const avatarSettings = () => {
    return <IconPicker url={user.settings.avatar} setUrl={setAvatarUrl} id={user.settings.id} />;
  };

  const settingsList = () => {
    return (
      <List disablePadding>
        <ListItemButton onClick={() => setProfileExpanded(!profileExpanded)}>
          <ListItemIcon>
            <AccountBox />
          </ListItemIcon>
          <ListItemText primary={"Profile"} />
          {profileExpanded ? <ExpandLess /> : <ExpandMore />}
        </ListItemButton>
        <Collapse in={profileExpanded} timeout="auto" unmountOnExit>
          <List component="div">
            <ListItem>
              <ListItemText disableTypography inset>
                {isLoading ? loading() : generalSettings()}
              </ListItemText>
            </ListItem>
          </List>
        </Collapse>

        <Divider />

        <ListItemButton onClick={() => setAvatarExpanded(!avatarExpanded)}>
          <ListItemIcon>
            <Face />
          </ListItemIcon>
          <ListItemText primary={"Display Picture"} />
          {avatarExpanded ? <ExpandLess /> : <ExpandMore />}
        </ListItemButton>
        <Collapse in={avatarExpanded} timeout="auto" unmountOnExit>
          <List
            component="div"
            sx={{
              paddingLeft: 4,
              paddingRight: 4
            }}>
            {isLoading ? loading() : avatarSettings()}
          </List>
        </Collapse>

        <Divider />

        <ListItemButton onClick={() => setNotificationsExpanded(!notificationsExpanded)}>
          <ListItemIcon>
            <NotificationsIcon />
          </ListItemIcon>
          <ListItemText primary="Notifications" />
          {notificationsExpanded ? <ExpandLess /> : <ExpandMore />}
        </ListItemButton>
        <Collapse in={notificationsExpanded} timeout="auto" unmountOnExit>
          <List component="div">
            <ListItem>
              <ListItemText disableTypography inset>
                {isLoading ? loading() : notificationsSettings()}
              </ListItemText>
            </ListItem>
          </List>
        </Collapse>

        {/* <Divider />

        <ListItem button onClick={() => setUnitsExpanded(!unitsExpanded)}>
          <ListItemIcon>
            <UnitsIcon />
          </ListItemIcon>
          <ListItemText primary="Preferred Units" />
          {unitsExpanded ? <ExpandLess /> : <ExpandMore />}
        </ListItem>
        <Collapse in={unitsExpanded} timeout="auto" unmountOnExit>
          <List component="div">
            <ListItem>
              <ListItemText disableTypography inset>
                {isLoading ? loading() : unitPreferences()}
              </ListItemText>
            </ListItem>
          </List>
        </Collapse>

        <Divider />

        <ListItem button onClick={() => setMapsExpanded(!mapsExpanded)}>
          <ListItemIcon>
            <FieldsIcon />
          </ListItemIcon>
          <ListItemText primary={"Map Settings"} />
          {mapsExpanded ? <ExpandLess /> : <ExpandMore />}
        </ListItem>
        <Collapse in={mapsExpanded} timeout="auto" unmountOnExit>
          <List component="div">
            <ListItem>
              <ListItemText disableTypography inset>
                {isLoading ? loading() : mapSettings()}
              </ListItemText>
            </ListItem>
          </List>
        </Collapse> */}
      </List>
    );
  };

  return (
    <ResponsiveDialog
      maxWidth="sm"
      fullWidth
      open={isOpen}
      onClose={closeDialog}
      aria-labelledby="user-settings-dialog">
      <AppBar position="relative">
        <Toolbar>
          <IconButton edge="start" color="inherit" onClick={closeDialog} aria-label="close">
            <Close />
          </IconButton>
          <UserAvatar user={user} />
          <Typography variant="h6" className={classes.title}>
            User Settings
          </Typography>
          <Button color="inherit" onClick={submit}>
            Save
          </Button>
        </Toolbar>
      </AppBar>
      {settingsList()}
    </ResponsiveDialog>
  );
}