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 { deleteType, fetchTypes, postType } from "../../helpers/types";
import EnhancedTableToolbar from "./components/enchancedTableToolbar";
import EnhancedTableHead from "./components/enchancedTableHead";
import { stableSort } from "./helpers/sorters";
import { getComparator } from "./helpers/comparators";

const rowsPerPage = 5;

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

export default function TypeTable() {
  // all Types
  const [data, setData] = useState([]);
  // searched Types
  const [searchedData, setSearchedData] = useState([]);
  // selected Types, stored only id of Type
  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 used for searching
  const [search, setSearch] = useState("");
  // name of new Type
  const [typeName, setTypeName] = useState("");

  // fetch Types on table mount
  useEffect(() => {
    fetchTypes().then((types) => setData(types));
  }, []);

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

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

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

    setSearchedData(filteredRows);
  };

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

    // delete each Type by its ID, if successful, add ID to deletedTypes
    selected.forEach((type_id) => {
      deleteType(type_id).then(deletedTypes.push(type_id));
    });

    // filter all Types in table and check, if they were deleted
    const new_data = data.filter(
      (type) => deletedTypes.indexOf(type.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 Types 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 = (name) => selected.indexOf(name) !== -1;

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

  // handler for changing value of new Type
  function handleTypeNameChange(e) {
    setTypeName(e.target.value);
  }

  // handler for adding new Type
  function handleAddType() {
    if (typeName.trim().length > 0) {
      // post new Type, if successful, add Type to data
      postType({ type: typeName }).then((res) => {
        setData([...data, res.data]);
      });
    }

    setTypeName("");
  }

  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 Type ID */}
        <TableCell
          component="th"
          id={row.id}
          padding="none"
          scope="row"
          align="right"
        >
          {row.id}
        </TableCell>
        {/* TableCell for text of Type */}
        <TableCell>
          <div
            style={{
              overflow: "hidden",
              textOverflow: "ellipsis",
              width: "11rem",
            }}
          >
            {row.type}
          </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 rows
          name="Types" // name of table
        />
        <TextField
          style={{ ml: 5 }}
          value={search}
          label="search"
          size="small"
          onChange={(val) => requestSearch(val.target.value)}
        />

        <TableContainer>
          <Table size="medium">
            <EnhancedTableHead
              numSelected={selected.length}
              order={order}
              orderBy={orderBy}
              onSelectAllClick={handleSelectAllClick}
              onRequestSort={handleRequestSort}
              rowCount={searchedData.length}
              headCells={headCells}
            />
            <TableBody>
              {
                // sort searched Types
                stableSort(searchedData, getComparator(order, orderBy))
                  // get Types for current page
                  .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
                  // map row into cells
                  .map((row, index) => {
                    // true if row is selected, otherwise false
                    const isItemSelected = isSelected(row.id);

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