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 Paper from "@mui/material/Paper";
import Checkbox from "@mui/material/Checkbox";
import IconButton from "@mui/material/IconButton";
import { TextField } from "@mui/material";
import AddCircleIcon from "@mui/icons-material/AddCircle";
import EnhancedTableHead from "./components/enchancedTableHead";
import EnhancedTableToolbar from "./components/enchancedTableToolbar";
import { stableSort } from "./helpers/sorters";
import { getComparator } from "./helpers/comparators";
import { deleteSign, postSign } from "../../helpers/signs";

const rowsPerPage = 5;

const headCells = [
  {
    id: "id",
    numeric: true,
    disablePadding: true,
    label: "ID",
  },
  {
    id: "sign",
    numeric: false,
    disablePadding: false,
    label: "Sign",
  },
];

/**
 * Table handling signs, handler for deleting can be passes and default handler
 * will be ignored.
 * @param {[Object]} signs array of Sign objects, will be in table
 * @param {function} handleDelete handler for deleting signs
 * @param {boolean} allowCreate if true, table will contain input field for creating signs
 */
export default function SignTable({ signs = [], handleDelete, allowCreate }) {
  const [data, setData] = useState(signs);
  // searched Gameruns
  const [searchedData, setSearchedData] = useState([]);
  // keyword
  const [search, setSearch] = useState("");
  // selected Gameruns, stored only id of Gamerun
  const [selected, setSelected] = React.useState([]);
  const [order, setOrder] = React.useState("asc");
  const [orderBy, setOrderBy] = React.useState("id");
  const [signName, setSignName] = useState("");
  const [page, setPage] = React.useState(0);

  // set data on table mount
  useEffect(() => {
    setData(signs);
  }, [signs]);

  // if array of Signs is modified, request search
  useEffect(() => {
    requestSearch(search);
  }, [data]);

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

    const filteredRows = data.filter((row) => {
      return (
        // search by sign id and text
        [row.id, row.text].filter((text) =>
          text.toString().toLowerCase().includes(searchedVal.toLowerCase())
        ).length > 0
      );
    });
    setSearchedData(filteredRows);
  };

  function handleDeleteSelected() {
    // if handler for deleting was provided
    if (handleDelete !== undefined) {
      handleDelete(selected); // call provided handler with IDs of selected Signs
      return;
    }

    let deletedSigns = [];

    // delete each Sign by its ID, if successful, add id to deletedSigns
    selected.forEach((sign_id) => {
      deleteSign(sign_id).then(deletedSigns.push(sign_id));
    });

    // filter all Signs and check, if they were deleted
    const new_data = data.filter(
      (sign) => deletedSigns.indexOf(sign.id) === -1
    );
    setSelected([]);
    setData(new_data);
  }

  // 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 Signs has been checked
    // add ids of all Signs 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 handleSignNameChange(e) {
    setSignName(e.target.value);
  }

  // handler for creating new sign
  function handleCreateSign() {
    if (signName.trim().length > 0) {
      // if new Sign post was successful, add that post into data hook
      postSign({ text: signName }).then((res) => {
        setData([...data, res.data]);
      });
    }
    // clear sign input field
    setSignName("");
  }

  // function used for creating rows in Sign table
  const tableCells = (row, isItemSelected) => {
    return (
      <React.Fragment>
        {/* TableCell for CheckBox */}
        <TableCell
          padding="checkbox"
          onClick={(event) => handleClick(event, row.id)}
        >
          <Checkbox color="primary" checked={isItemSelected} />
        </TableCell>
        {/* TableCell for Sign ID */}
        <TableCell
          component="th"
          id={row.id}
          padding="none"
          scope="row"
          align="right"
        >
          {row.id}
        </TableCell>
        {/* TableCell for text of Sign */}
        <TableCell>
          <div
            style={{
              overflow: "hidden",
              textOverflow: "ellipsis",
              width: "11rem",
            }}
          >
            {row.text}
          </div>
        </TableCell>
      </React.Fragment>
    );
  };

  return (
    <Box
      justifyContent="center"
      alignContent="center"
      sx={{ display: "flex", width: "100%" }}
    >
      <Paper sx={{ width: "90%" }}>
        <EnhancedTableToolbar
          numSelected={selected.length}
          onDelete={handleDeleteSelected} // handler for deleting selected rows
          name="Signs" // name of table
        />
        {/* Search TextField */}
        <TextField
          style={{ ml: 5 }}
          value={search} // searched keyword
          label="search"
          size="small"
          onChange={(val) => requestSearch(val.target.value)}
        />

        <TableContainer>
          <Table sx={{}} aria-labelledby="tableTitle" size="medium">
            <EnhancedTableHead
              numSelected={selected.length}
              order={order}
              orderBy={orderBy}
              onSelectAllClick={handleSelectAllClick}
              onRequestSort={handleRequestSort}
              rowCount={searchedData.length}
              headCells={headCells}
            />
            <TableBody>
              {
                // sort searched Signs
                stableSort(searchedData, getComparator(order, orderBy))
                  // get Signs for current page
                  .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
                  // map Sign into row of TableCells
                  .map((row, index) => {
                    const isItemSelected = isSelected(row.id);
                    const id = `enhanced-table-checkbox-${index}`;

                    return (
                      <TableRow
                        hover
                        role="checkbox"
                        tabIndex={-1}
                        key={row.id}
                        selected={isItemSelected}
                      >
                        {tableCells(row, isItemSelected)}
                      </TableRow>
                    );
                  })
              }
              {
                // generate empty rows if there is not enough signs for current page
                emptyRows > 0 && (
                  <TableRow
                    style={{
                      height: 53 * emptyRows,
                    }}
                  >
                    <TableCell colSpan={6} />
                  </TableRow>
                )
              }
            </TableBody>
          </Table>
        </TableContainer>
        {/* Textfield for creating new sign */}
        <Box style={{ display: "flex", paddingLeft: 50, paddingRight: 50 }}>
          {/* if creating new signs is allowed, render textfield */}
          {allowCreate && (
            <TextField
              fullWidth
              size="small"
              style={{ px: 5 }}
              value={signName}
              label="New sign"
              onChange={handleSignNameChange}
              InputProps={{
                // buttton in textfield
                endAdornment: (
                  <IconButton onClick={handleCreateSign}>
                    <AddCircleIcon color="primary" />
                  </IconButton>
                ),
              }}
            />
          )}
        </Box>
        <TablePagination
          rowsPerPageOptions={[]}
          labelRowsPerPage=""
          component="div"
          count={searchedData.length}
          rowsPerPage={rowsPerPage}
          page={page}
          onPageChange={handleChangePage}
        />
      </Paper>
    </Box>
  );
}
