import * as React from "react";
import { useEffect, useState } from "react";
import Box from "@mui/material/Box";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TablePagination from "@mui/material/TablePagination";
import TableRow from "@mui/material/TableRow";
import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton";
import InfoIcon from "@mui/icons-material/Info";
import { makeStyles } from "@material-ui/core";
import { Link } from "react-router-dom";
import Paper from "@mui/material/Paper";
import EnhancedTableToolbar from "./components/enchancedTableToolbar";
import { TextField } from "@mui/material";
import EnhancedTableHead from "./components/enchancedTableHead";
import { stableSort } from "./helpers/sorters";
import { getComparator } from "./helpers/comparators";
import Checkbox from "@mui/material/Checkbox";
import {
  deleteEmail,
  fetchEmails,
  fetchEmailsByGamerunID,
} from "../../helpers/emails";

const useStyles = makeStyles({
  ellipsis: {
    maxWidth: 200,
    whiteSpace: "nowrap",
    overflow: "hidden",
    textOverflow: "ellipsis",
  },
});

const rowsPerPage = 6;

const headCells = [
  {
    id: "id",
    numeric: true,
    disablePadding: true,
    label: "ID",
  },
  {
    id: "subject",
    numeric: false,
    disablePadding: false,
    label: "Subject",
  },
  {
    id: "body",
    numeric: false,
    disablePadding: false,
    label: "Body",
  },
  {
    id: "type",
    numeric: false,
    disablePadding: false,
    label: "Type",
  },
];

/**
 * Table handling emails, if gamerunID is passed,
 * show emails related to the gamerun
 * @param {number} gamerunID ID of gamerun, not required
 * @param {boolean} hideCheckbox show or hide checkboxes in rows
 */
export default function EmailTable({ gamerunID, hideCheckbox = false }) {
  const classes = useStyles();
  // non searched Emails
  const [data, setData] = useState([]);
  // searched Emails
  const [searchedData, setSearchedData] = useState([]);
  // selected Emails, stored only id of Email
  const [selected, setSelected] = React.useState([]);
  // sorting order = ascending/descending
  const [order, setOrder] = React.useState("asc");
  // which column is used for sorting
  const [orderBy, setOrderBy] = React.useState("id");
  // current table page
  const [page, setPage] = React.useState(0);
  // keyword
  const [search, setSearch] = useState("");

  // fetch emails on table mount
  useEffect(() => {
    if (gamerunID) {
      // if gamerunID is present, fetch emails by gamerunID
      fetchEmailsByGamerunID(gamerunID).then((emails) => {
        setData(emails);
      });
    } else {
      // if gamerunID is undefined, fetch all emails
      fetchEmails().then((emails) => {
        setData(emails);
      });
    }
  }, []);

  // when emails are updated (removed or added), request search
  useEffect(() => {
    requestSearch(search);
  }, [data]);

  const requestSearch = (searchedVal) => {
    setSearch(searchedVal); // set keyword
    setSelected([]); // clear hook with selected Emails

    const filteredRows = data.filter((row) => {
      return (
        // search by email id, subject, body and type
        [row.id, row.subject, row.body, row.type.type].filter(
          (text) =>
            !!text &&
            text.toString().toLowerCase().includes(searchedVal.toLowerCase()) // check if text contains searched value
        ).length > 0
      );
    });

    setSearchedData(filteredRows);
  };

  const handleDeleteSelected = () => {
    let deletedEmails = [];

    //delete each Email by its id, if successful, add id to deletedEmails
    selected.forEach((email_id) => {
      deleteEmail(email_id).then(deletedEmails.push(email_id));
    });

    // filter all Emails and check, if they were deleted
    const new_data = data.filter(
      (email) => deletedEmails.indexOf(email.id) === -1
    );

    setData(new_data);
    setSelected([]);
  };

  // handler for changing order and column used for sorting
  const handleRequestSort = (event, property) => {
    const isAsc = orderBy === property && order === "asc";
    setOrder(isAsc ? "desc" : "asc");
    setOrderBy(property);
  };

  const handleSelectAllClick = (event) => {
    // if checkbox for selecting all Emails has been checked
    // add ids of all Emails to selected hook, otherwise clear selected
    if (event.target.checked) {
      const newSelecteds = searchedData.map((n) => n.id);
      setSelected(newSelecteds);
      return;
    }
    setSelected([]);
  };

  // handler for selecting/unselecting row
  const handleClick = (event, id) => {
    const selectedIndex = selected.indexOf(id);
    let newSelected = [];

    if (selectedIndex === -1) {
      newSelected = newSelected.concat(selected, id);
    } else if (selectedIndex === 0) {
      newSelected = newSelected.concat(selected.slice(1));
    } else if (selectedIndex === selected.length - 1) {
      newSelected = newSelected.concat(selected.slice(0, -1));
    } else if (selectedIndex > 0) {
      newSelected = newSelected.concat(
        selected.slice(0, selectedIndex),
        selected.slice(selectedIndex + 1)
      );
    }

    setSelected(newSelected);
  };

  const handleChangePage = (event, newPage) => {
    setPage(newPage);
  };

  const isSelected = (id) => selected.indexOf(id) !== -1;

  // compute empty rows on current page
  const emptyRows =
    page > 0
      ? Math.max(0, (1 + page) * rowsPerPage - searchedData.length)
      : rowsPerPage - searchedData.length;

  // function used for creating rows in Email table
  function tableCells(row, isRowSelected) {
    return (
      <React.Fragment>
        {/* TableCell for CheckBox */}
        <TableCell
          sx={{ display: hideCheckbox ? "none" : "" }}
          hidden={true}
          padding="checkbox"
          onClick={(event) => handleClick(event, row.id)}
        >
          <Checkbox color="primary" checked={isRowSelected} />
        </TableCell>
        {/* TableCell for email ID */}
        <TableCell
          component="th"
          id={row.id}
          padding="none"
          scope="row"
          align="right"
        >
          <Typography variant="inherit" className={classes.ellipsis}>
            {row.id}
          </Typography>
        </TableCell>
        {/* TableCell for email subject */}
        <TableCell>
          <Typography variant="inherit" className={classes.ellipsis}>
            {row.subject}
          </Typography>
        </TableCell>
        {/* TableCell for email body */}
        <TableCell>
          <div className={classes.ellipsis}>{row.body}</div>
        </TableCell>
        {/* TableCell for text of email's type */}
        <TableCell>
          <Typography variant="inherit" className={classes.ellipsis}>
            {row.type.type}
          </Typography>
        </TableCell>
        {/* TableCell for InfoIcon, onclick redirects to info page of the email */}
        <TableCell padding="checkbox">
          <Link to={`/settings/emails/${row.id}`}>
            <IconButton color="primary">
              <InfoIcon />
            </IconButton>
          </Link>
        </TableCell>
      </React.Fragment>
    );
  }

  return (
    <Box
      justifyContent="center"
      alignContent="center"
      sx={{ display: "flex", width: "100%" }}
    >
      <Paper sx={{ minWidth: "350px", width: "95%", mt: 5 }}>
        <EnhancedTableToolbar
          numSelected={selected.length}
          onDelete={handleDeleteSelected} // handler for deleting rows
          name="Emails" // name of table
        />
        {/* Search TextField */}
        <TextField
          style={{ ml: 5 }}
          value={search} // searched keyword
          label="search"
          size="small"
          onChange={(e) => requestSearch(e.target.value)}
        />
        <TableContainer>
          <Table size="medium">
            <EnhancedTableHead
              numSelected={selected.length}
              order={order}
              orderBy={orderBy}
              onSelectAllClick={handleSelectAllClick}
              onRequestSort={handleRequestSort}
              rowCount={searchedData.length}
              headCells={headCells}
              iconCell={true}
              hideCheckbox={hideCheckbox}
            />
            <TableBody>
              {
                // sort searched emails
                stableSort(searchedData, getComparator(order, orderBy))
                  // get emails for current page
                  .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
                  // map row into cells
                  .map((row) => {
                    // true if row is selected, otherwise false
                    const isRowSelected = isSelected(row.id);

                    return (
                      <TableRow
                        hover
                        role="checkbox"
                        tabIndex={-1}
                        key={row.id}
                        selected={isRowSelected}
                      >
                        {tableCells(row, isRowSelected)}
                      </TableRow>
                    );
                  })
              }
              {
                // generate empty row if there is not enough emails for current page
                emptyRows > 0 && (
                  <TableRow
                    style={{
                      height: 53 * emptyRows,
                    }}
                  >
                    <TableCell colSpan={6} />
                  </TableRow>
                )
              }
            </TableBody>
          </Table>
        </TableContainer>
        <TablePagination
          rowsPerPageOptions={[]}
          component="div"
          count={data.length}
          rowsPerPage={rowsPerPage}
          page={page}
          onPageChange={handleChangePage}
        />
      </Paper>
    </Box>
  );
}
