import { Box, Chip, Grid2, Theme, Tooltip } from "@mui/material";
import SmartBreadcrumb from "common/SmartBreadcrumb";
import { Device, Group } from "models"
import { useEffect, useState } from "react"
import { useLocation, useNavigate, useParams } from "react-router-dom";
import PageContainer from "./PageContainer";
import { useDeviceAPI, useGlobalState, useGroupAPI } from "providers";
import GroupActions from "group/GroupActions";
import { pond } from "protobuf-ts/pond";
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
import ResponsiveTable, { Column } from "common/ResponsiveTable";
import { or } from "utils/types";
import { appendToUrl } from "navigation/Router";
import { getDeviceStateHelper } from "pbHelpers/DeviceState";
import { makeStyles } from "@mui/styles";
import { blue, green } from "@mui/material/colors";
import { cloneDeep } from "lodash";

const useStyles = makeStyles((theme: Theme) => {
  return ({
    buttonBox: {
      position: "absolute", 
      zIndex: 1, 
      right: theme.spacing(4),
      transform: "translateY(-50%)", // Move it up by half its height
      transition: "opacity 0.2s ease-in-out",
      opacity: 1,
      // top: 0,
    },
    fadeBox: {
      opacity: 0, // Fully transparent by default
      transition: "opacity 0.2s ease-in-out", // Smooth transition
      "&:hover": {
        opacity: 1, // Fully opaque on hover
      },
    },
    provisionIcon: {
      color: blue["700"]
    },
    cellContainer: {
      margin: theme.spacing(1),
      marginLeft: theme.spacing(2),
      display: "flex",
      // justifyContent: "center",
    },
    green: {
      color: green["600"]
    },
    tab: {
      display: "block",
      overflow: "hidden",
      textOverflow: "ellipsis",
      maxWidth: theme.spacing(26),
      whiteSpace: "nowrap",
      padding: theme.spacing(1.5)
    }
  });
});


export default function GroupPage() {

  const groupAPI = useGroupAPI()
  const deviceAPI = useDeviceAPI()
  const navigate = useNavigate()
  const classes = useStyles()
  
  const groupID = parseInt(useParams<{ groupID: string }>()?.groupID ?? "0");
  const { state } = useLocation();
  const [{as}] = useGlobalState();
  const [group, setGroup] = useState<Group>(state?.group ? Group.create(state.group) : Group.create())
  const [loadingGroup, setLoadingGroup] = useState(false)
  const [loadingDevices, setLoadingDevices] = useState(false)
  const [devices, setDevices] = useState<Device[]>([])
  const [permissions, setPermissions] = useState<pond.Permission[]>([])
  const [limit, setLimit] = useState(10)
  const [total, setTotal] = useState(0)
  const [page, setPage] = useState(0)
  const [order, ] = useState<"asc" | "desc">("asc")
  const [orderBy, ] = useState("")
  const [search, setSearch] = useState("")

  const loadGroup = () => {
    setLoadingGroup(true)
    groupAPI.getGroupAndPermissions(groupID).then(resp => {
      if (resp.data.group) setGroup(Group.create(resp.data.group))
      let newPerms: pond.Permission[] = []
      resp.data.permissions.forEach(perm => {
        if (typeof(perm) === "string") {
          const permNumber = pond.Permission[perm as keyof typeof pond.Permission]
          newPerms.push(permNumber)
        } else {
          newPerms.push(perm)
        }
      })
      setPermissions(newPerms)
    }).finally(() => {
      setLoadingGroup(false)
    })
  }

  useEffect(() => {
    // if (group.id() === groupID) return;
    loadGroup()
  // }, [group, groupID])
  }, [])

  const getKeys = () => {
    let keys = getContextKeys()
    keys.push(groupID.toString())
    return keys
  }

  const getTypes = () => {
    let keys = getContextTypes()
    keys.push("group")
    return keys
  }


  const loadDevices = () => {
    setLoadingDevices(true)
    deviceAPI.list(
      limit, 
      page*limit, 
      order, 
      orderBy, 
      search,
      undefined,
      undefined,
      undefined,
      undefined,
      undefined,
      undefined,
      getKeys(),
      getTypes(),
      undefined,
      undefined,
      as
    ).then(resp => {
      let newDevices: Device[] = [];
      resp.data.devices.forEach(device => {
        newDevices.push(Device.create(device))
      })
      setDevices(newDevices)
      setTotal(resp.data.total)
    }).finally(() => {
      setLoadingDevices(false)
    })
  }

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

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

  const columns = (): Column<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 > 20
                    ? description.substring(0, 20) + "..."
                    : description}
                </span>
              </Tooltip>
            </Box>
          )
        }
      },
    ]
  }

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

  return (
    <PageContainer>
      <Grid2 container justifyContent={"space-between"} alignItems={"center"} paddingBottom={2}>
        <Grid2 >
          <SmartBreadcrumb groupName={group.name()} loading={loadingGroup} />
        </Grid2>
        <Grid2 marginTop={"auto"} marginBottom="auto">
          <GroupActions 
            group={group}
            permissions={permissions ? permissions : []} 
            devices={devices} 
            refreshCallback={() => {}} 
          />
        </Grid2>
      </Grid2>
      <ResponsiveTable<Device>
        title={group.name()}
        subtitle={group.settings.description}
        rows={devices}
        columns={columns()}
        total={total}
        pageSize={limit}
        page={page}
        setPage={setPage}
        handleRowsPerPageChange={handleChange}
        onRowClick={toDevice}
        setSearchText={setSearch}
        isLoading={loadingDevices}
        loadMore={()=>{
          let current = cloneDeep(devices)
          setLoadingDevices(true)
          deviceAPI.list(
            limit, 
            current.length, 
            order, 
            orderBy, 
            search,
            undefined,
            undefined,
            undefined,
            undefined,
            undefined,
            undefined,
            getKeys(),
            getTypes(),
            undefined,
            undefined,
            as
          ).then(resp => {
            let newDevices: Device[] = [];
            resp.data.devices.forEach(device => {
              newDevices.push(Device.create(device))
            })
            setDevices(current.concat(newDevices))
          }).finally(() => {
            setLoadingDevices(false)
          })
        }}
      />
    </PageContainer>
  )
}