import { DeveloperBoard as ProvisionIcon, LibraryAdd as CreateGroupIcon } from "@mui/icons-material";
import { Box, Chip, IconButton, Theme, Tooltip, Typography } from "@mui/material";
import { blue, green } from "@mui/material/colors";
import { makeStyles } from "@mui/styles";
import ResponsiveTable, { Column } from "common/ResponsiveTable";
import ProvisionDevice from "device/ProvisionDevice";
import { pond } from "protobuf-ts/pond";
import { useDeviceAPI, useGroupAPI } from "providers";
import { useEffect, useState } from "react";
import PageContainer from "./PageContainer";
import { useMobile } from "hooks";
import { useLocation, useNavigate } from "react-router-dom";
import { or } from "utils/types";
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
import { getDeviceStateHelper } from "pbHelpers/DeviceState";
import { Group } from "models";
import GroupSettings from "group/GroupSettings";

const useStyles = makeStyles((theme: Theme) => {
  return ({
    provisionIcon: {
      color: blue["700"]
    },
    cellContainer: {
      margin: theme.spacing(1),
      marginLeft: theme.spacing(2),
      display: "flex",
      // justifyContent: "center",
    },
    green: {
      color: green["600"]
    },
  });
});

export default function Devices() {
  const isMobile = useMobile();
  const classes = useStyles();
  const navigate = useNavigate();
  const location = useLocation();
  const deviceAPI = useDeviceAPI();
  const groupAPI = useGroupAPI();
  const [limit, setLimit] = useState(10);
  const [page, setPage] = useState(0);
  const [order, ] = useState<"asc" | "desc">("asc");
  const [orderBy, ] = useState("name");
  const [search, setSearch] = useState("");
  const [total, setTotal] = useState(0);
  const [devices, setDevices] = useState<pond.Device[]>([])
  const [isProvisionDialogOpen, setIsProvisionDialogOpen] = useState<boolean>(false);

  const [groupLimit, setGroupLimit] = useState(10);
  const [groupPage, setGroupPage] = useState(0);
  const [orderGroup, ] = useState<"asc" | "desc">("asc");
  const [orderGroupBy, ] = useState("name");
  const [searchGroup, setGroupSearch] = useState("");
  const [totalGroups, setTotalGroups] = useState(0);

  const [selectedGroup, setSelectedGroup] = useState<Group | undefined>(undefined);
  const [groupSettingsMode, setGroupSettingsMode] = useState<
    "add" | "update" | "remove" | undefined
  >(undefined);
  const [groupSettingsIsOpen, setGroupSettingsIsOpen] = useState<boolean>(false);

  const openProvisionDialog = () => {
    setIsProvisionDialogOpen(true);
  };

  const closeProvisionDialog = () => {
    setIsProvisionDialogOpen(false);
  };

  const openGroupSettings = (
    group: Group | undefined,
    mode: "add" | "update" | "remove" | undefined
  ) => {
    setGroupSettingsIsOpen(true);
    setGroupSettingsMode(mode);
    setSelectedGroup(group);
  };

  const closeGroupSettings = (event: any) => {
    setGroupSettingsIsOpen(false);
    setGroupSettingsMode(undefined);
    setSelectedGroup(undefined);
  };

  const loadGroups = () => {
    groupAPI.listGroups(
      groupLimit,
      groupPage*groupLimit, 
      orderGroup, 
      orderGroupBy, 
      searchGroup,
    ).then(resp => {
      console.log(resp.data)
    })
  }

  const loadDevices = () => {
    deviceAPI.list(
      limit, 
      page*limit, 
      order, 
      orderBy, 
      search,
      undefined,
      undefined,
      undefined,
      undefined,
      undefined,
      undefined,
      getContextKeys(),
      getContextTypes()
    ).then(resp => {
      setDevices(resp.data.devices)
      setTotal(resp.data.total)
    })
  }

  useEffect(() => {
    loadDevices()
  }, [limit, page, order, orderBy, search])

  useEffect(() => {
    loadGroups()
  }, [groupLimit, groupPage, orderGroup, orderGroupBy, searchGroup])


  const handleChange = (event: any) => {
    setLimit(event.target.value);
  };

  const appendToUrl = (appendage: number | string) => {
    const basePath = location.pathname.replace(/\/$/, ""); 
    return(`${basePath}/${appendage}`);
  };

  const toDevice = (device: pond.Device) => {
    navigate(appendToUrl(or(device.settings?.deviceId, "")), { state: {device: device} })
  };

  const columns = (): Column<pond.Device>[] => {
    return [
      {
        title: "State",
        render: (device) => {
          const status = device.status ?? pond.DeviceStatus.create()
          const deviceStateHelper = getDeviceStateHelper(status.state);
          return (
            <Box className={classes.cellContainer}>
              <Tooltip title={deviceStateHelper.description}>{deviceStateHelper.icon}</Tooltip>
            </Box>
          )
        }
      },
      {
        title: "ID",
        render: device => <span className={classes.cellContainer}>
            {device.settings?.deviceId}
          </span>
      },
      {
        title: "Device",
        render: (device) => {
          return (
            <Box className={classes.cellContainer} >
              <Chip 
                variant="outlined"
                label={device.settings?.name ? device.settings.name : "Device " + device.settings?.deviceId} 
              />
            </Box>
            
          )
        }
      },
      {
        title: "Description",
        render: device => {
          const description = device.settings?.description ?? ""
          return (
            <Box className={classes.cellContainer}>
              <Tooltip title={device.settings?.description}>
                <span>
                  {description.length > 10
                    ? description.substring(0, 10) + "..."
                    : description}
                </span>
              </Tooltip>
            </Box>
          )
        }
      },
    ]
  }

  const provisionButton= () => {
    return (
      <Tooltip title="Provision Device">
        <IconButton onClick={openProvisionDialog} aria-label="Provision Device">
          <ProvisionIcon className={classes.provisionIcon} />
        </IconButton>
      </Tooltip>
    )
  }

  const groupButton = () => {
    return (
      <Tooltip title="Create Group">
        <IconButton
          onClick={() => openGroupSettings(undefined, "add")}
          aria-label="Create Group">
          <CreateGroupIcon className={classes.green} />
        </IconButton>
      </Tooltip>
    )
  }

  const subtitle = () => {
    return (
      <>
      {provisionButton()}
      {groupButton()}
      </>
    )
  }

  return(
    <PageContainer padding={isMobile ? 0 : 2}>
      <ResponsiveTable<pond.Device>
        title="Devices"
        subtitle={subtitle()}
        rows={devices}
        columns={columns()}
        total={total}
        pageSize={limit}
        page={page}
        setPage={setPage}
        handleRowsPerPageChange={handleChange}
        onRowClick={toDevice}
        setSearchText={setSearch}
      />
      <ProvisionDevice
        isOpen={isProvisionDialogOpen}
        refreshCallback={loadDevices}
        closeDialogCallback={closeProvisionDialog}
      />
      <GroupSettings
        initialGroup={selectedGroup}
        mode={groupSettingsMode}
        isDialogOpen={groupSettingsIsOpen}
        closeDialogCallback={closeGroupSettings}
        refreshCallback={loadGroups}
        canEdit={true}
      />
    </PageContainer>
  )
}