import React, { useEffect, useState } from "react";
import {
  Theme,
  ListItem,
  ListItemAvatar,
  Avatar,
  ListItemText,
  Typography,
  ListItemButton,
  Box,
  IconButton,
  Grid2,
} from "@mui/material";
import { pond } from "protobuf-ts/pond";
import { useGlobalState, useSnackbar, useTeamAPI, useUserAPI } from "providers";
import { Team, teamScope } from "models";
import { useNavigate } from "react-router";
import { cloneDeep } from "lodash";
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
import { makeStyles } from "@mui/styles";
import TeamActions from "./TeamActions";
import ResponsiveTable, { Column } from "common/ResponsiveTable";
import { useMobile } from "hooks";
import { AddBox } from "@mui/icons-material";
import TeamSettings from "./TeamSettings";

const useStyles = makeStyles((theme: Theme) => ({
  cardContent: {
    padding: theme.spacing(1)
  },
  clickable: {
    "&:hover": {
      textDecoration: "underline",
      cursor: "pointer"
    }
  },
  input: {
    marginLeft: "auto",
    marginRight: theme.spacing(2),
    marginTop: theme.spacing(1)
  },
  button: {
    width: theme.spacing(6),
    height: theme.spacing(6),
    marginTop: "auto",
    marginBottom: "auto",
  },
  titleBox: {
    display: "flex",
    alignItems: "center",
    marginLeft: theme.spacing(1),
    width: "100%"
  }
}))

export default function TeamList() {
  const classes = useStyles();
  const [teams, setTeams] = useState<Team[]>([]);
  const teamAPI = useTeamAPI();
  const userAPI = useUserAPI();
  const history = useNavigate();
  const isMobile = useMobile()
  const snackbar = useSnackbar();
  const [{ user, as, team }] = useGlobalState();
  const [teamPerms, setTeamPerms] = useState<Map<string | number, pond.Permission[]>>(new Map());
  const [teamPrefs, setTeamPrefs] = useState<Map<string | number, pond.TeamPreferences> >(new Map());
  const [total, setTotal] = useState<number>(0);
  const [limit, setLimit] = useState<number>(5);
  const [page, setPage] = useState<number>(0);
  const [loading, setLoading] = useState<boolean>(true);
  const [search, setSearch] = useState<string>("");
  const [teamDialogOpen, setTeamDialogOpen] = useState<boolean>(false);

  const loadTeams = () => {
    setLoading(true);
    let newTeamPerms: Map<string | number, pond.Permission[]> = new Map();
    let newTeamPrefs: Map<string | number, pond.TeamPreferences> = new Map();
    let viewAs: string | undefined = as
    if (as === team.key()) {
      viewAs = undefined
    }
    teamAPI
      .listTeams(limit, limit * page, undefined, "name", undefined, undefined, " ", search)
      .then(resp => {
        setTotal(resp.data.total ? resp.data.total : 0);
        let newTeams: Team[] = []
        resp.data.teams.forEach(team => {
          let u = viewAs ? viewAs : user.id();
          let t = Team.create(team)
          if (team.settings && u !== "") {
            userAPI
              .getUser(u, teamScope(team.settings.key))
              .then(resp => {
                newTeamPerms.set(t.key(), resp.permissions)
                newTeamPrefs.set(t.key(), resp.preferences)
                t.preferences = cloneDeep(resp.preferences)
                t.permissions = cloneDeep(resp.permissions)
              }).catch(() => {
                snackbar.error("Error loading teams.")
              })
              .finally(() => {
                setTeamPerms(newTeamPerms);
                setTeamPrefs(newTeamPrefs);
              });
          }
          newTeams.push(t)
        });
        setTeams(newTeams);
      })
      .finally(() => {
        setLoading(false);
      });
  };

  useEffect(() => {
    loadTeams();
  }, [limit, page, search, as]);

  const columns = (): Column<Team>[] => {
    return [
      {
        title: "",
        render: team => {
          let permissions = teamPerms.get(team.settings?.key);
          if (!permissions) {
            permissions = [];
          }
          let preferences = teamPrefs.get(team.id());
          if (!preferences) {
            preferences = pond.TeamPreferences.create();
          }
          return (
            <ListItem
            alignItems="flex-start"
            disablePadding={!isMobile}
            secondaryAction={
              <TeamActions
                team={team}
                permissions={permissions}
                refreshCallback={loadTeams}
                removeSelfCallback={loadTeams}
                preferences={preferences}
                toggleNotificationPreference={() => {
                  if (preferences) {
                    let newTeamPrefs = cloneDeep(teamPrefs);
                    let prefs = newTeamPrefs.get(team.id()) ?? pond.TeamPreferences.create()
                    prefs.notify = !newTeamPrefs.get(team.id())?.notify
                    newTeamPrefs.set(team.id(), prefs)
                    teamAPI
                      .updatePreferences(
                        team.key(),
                        prefs,
                        getContextKeys(),
                        getContextTypes()
                      )
                      .then(() => {
                        setTeamPrefs(newTeamPrefs);
                      });
                  }
                }}
              />
            }
            >
              <ListItemButton
                onClick={() => {
                  if (team.settings) history(team.settings.key, { state: {team: team} });
                }}
              >
                <ListItemAvatar sx={{ marginLeft: isMobile ? -2 : 0 }}>
                  <Avatar
                    onClick={() => {
                      if (team.settings) history(team.settings.key);
                    }}
                    src={team.settings?.avatar}
                    alt=""
                    className={classes.clickable}
                  />
                </ListItemAvatar>
                <ListItemText
                  primary={
                    <Typography fontWeight={"bold"}>
                      {team.settings?.name}
                    </Typography>
                  }
                  secondary={
                    !isMobile && <React.Fragment>
                      <Typography component="span" variant="body2" color="textSecondary">
                        {team.settings?.info}
                      </Typography>
                    </React.Fragment>
                  }
                />
              </ListItemButton>
            </ListItem>
          )
        }
      }
    ]
  }

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

  const renderGutter = (team: Team) => {
    return(
      <Typography variant="body2" color="textSecondary" sx={{ padding: 1 }}>
        {team.settings.info}
      </Typography>
    )
  }

  const renderTitle = () => {
    return (
      <Box className={classes.titleBox}>
        <Avatar
          src={user.settings.avatar}
        />
        <Grid2 container direction="column" marginLeft={1}>
          <Grid2 marginBottom={-0.25}>
            <Typography variant="h6">
              {user.name()}'s Teams
            </Typography>
          </Grid2>
          <Grid2 marginTop={-0.25}>
            <Typography variant="body2">
              All teams you are a member of.
            </Typography>
          </Grid2>
        </Grid2>
        
        <IconButton onClick={() => setTeamDialogOpen(true)} color="primary" className={classes.button}>
          <AddBox/>
        </IconButton>
      </Box>
    )
  }

  return (
    <>
    <ResponsiveTable<Team>
      title={renderTitle()}
      rows={teams}
      columns={columns()}
      handleRowsPerPageChange={handleChange} 
      total={total} 
      pageSize={limit} 
      page={page} 
      setPage={setPage}
      setSearchText={setSearch}
      isLoading={loading}
      renderGutter={isMobile ? renderGutter : undefined}
      hideKeys
      loadMore={() => {
        let current = cloneDeep(teams)
        setLoading(true);
        let newTeamPerms: Map<string | number, pond.Permission[]> = new Map();
        let newTeamPrefs: Map<string | number, pond.TeamPreferences> = new Map();
        let viewAs: string | undefined = as
        if (as === team.key()) {
          viewAs = undefined
        }
        teamAPI
      .listTeams(limit, current.length, undefined, "name", undefined, undefined, " ", search)
      .then(resp => {
        setTotal(resp.data.total ? resp.data.total : 0);
        let newTeams: Team[] = []
        resp.data.teams.forEach(team => {
          let u = viewAs ? viewAs : user.id();
          let t = Team.create(team)
          if (team.settings && u !== "") {
            userAPI
              .getUser(u, teamScope(team.settings.key))
              .then(resp => {
                newTeamPerms.set(t.key(), resp.permissions)
                newTeamPrefs.set(t.key(), resp.preferences)
                t.preferences = cloneDeep(resp.preferences)
                t.permissions = cloneDeep(resp.permissions)
              }).catch(() => {
                snackbar.error("Error loading teams.")
              })
              .finally(() => {
                setTeamPerms(newTeamPerms);
                setTeamPrefs(newTeamPrefs);
              });
          }
          newTeams.push(t)
        });
        setTeams(current.concat(newTeams));
      })
      .finally(() => {
        setLoading(false);
      });
      }}
    />
    <TeamSettings
      teamDialogOpen={teamDialogOpen}
      closeTeamDialogCallback={() => setTeamDialogOpen(false)}
      refreshCallback={loadTeams}
    />
    </>
  )

}
