import * as React from "react";
import Checkbox from "@material-ui/core/Checkbox";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import TablePagination from "@material-ui/core/TablePagination";
import moment from "moment";

import {
  DataCard,
  FilterGroup,
  AlphabetFilter,
  BulkActionsMenu,
  BulkSelectedActions,
  EmptyStateComponent,
} from "./components";

import {
  DisplayItemsProps,
  DisplayItemsPropsType,
  DisplayItemsFieldDataType,
} from "./components/types";
import { Button, Icon } from "@material-ui/core";

/**
 * A module for displaying and filtering data with tools for hooking actions into the resulting records
 */
export const DisplayItems: React.FC<DisplayItemsProps> = ({
  name,
  type,
  data,
  fields,
  loading,
  loadingComponent,
  title,
  bulkActions,
  bulkActionsComponent,
  showbulkActions,
  dataItemActions,
  dataItemComponent,
  showCheckboxes,
  filterComponent,
  showFilterControls,
  currentFilter,
  showAlphabetFilter,
  emptyStateComponent,
  tags,
  showTags,
  showHeaders,
  showPagination,
  paginationSettings,
  enableSorting,
  onCreate,
  onUpdate,
  onDelete,
  onSelect,
  onSelectAll,
  onRowActionSelect,
  onFilterChange,
  onFilterSave,
  onSort,
  onExport,
  onImport,
  onBulkActionSelect,
  onPaginationChange,
}: DisplayItemsProps) => {
  const [selectedItems, setSelectedItems] = React.useState<any[]>([]);

  /**
   * Triggered when page change occurs
   * @params
   */
  const goToPage = (): void => {};

  /**
   * Triggered when pagination rows per page option changes
   * @params
   */
  const setRowsPerPage = (): void => {};

  /**
   * CSV download of the active filtered record set
   * @params
   */
  const exportData = (): void => {};

  /**
   * Method to select all of the items in the current view or filter
   * @params
   */
  const selectAll = (checked: boolean) => {
    if (checked) setSelectedItems([...data.map((i, k) => k)]);
    if (!checked) setSelectedItems([]);
  };

  /**
   * Method to select one of the items in the current view or filter
   * @params
   */
  const selectItem = (i: any, checked: boolean): void => {
    if (checked) setSelectedItems([...selectedItems, i]);
    else setSelectedItems(selectedItems.filter((itm) => itm !== i));
  };

  const handleFilterChange = (filter: any): void => {
    const doOwnFilter: boolean = onFilterChange(filter);

    if (doOwnFilter) {
      // do local filter
      console.log("Filter");
    }
  };

  // Show the default loading component (or one provided) if we're loading
  if (loading) {
    if (loadingComponent)
      return (
        <div data-testid="DisplayItems-LoadingCustom">{loadingComponent}</div>
      );
    else return <div data-testid="DisplayItems-Loading">Loading...</div>;
  }

  // Show the default empty state component (or the one provided) if there is no data to show
  if (!loading && !data.length) {
    if (emptyStateComponent)
      return (
        <div data-testid="DisplayItems-EmptyStateCustom">
          {emptyStateComponent}
        </div>
      );
    else
      return (
        <div data-testid="DisplayItems-EmptyState">
          <EmptyStateComponent />
        </div>
      );
  }

  const displayFieldValue = (row, itm) => {
    if (itm.type === DisplayItemsFieldDataType.DATE)
      return moment(row[itm.name]).format("MMM Do, YYYY");
    if (itm.type === DisplayItemsFieldDataType.BOOLEAN)
      return row[itm.name] ? "Yes" : "No";
    return row[itm.name].toString();
  };

  return (
    <div data-testid="DisplayItems-Default">
      {showAlphabetFilter && (
        <AlphabetFilter
          onClick={(ch) =>
            onFilterChange({ allFields: ch, condition: "contains" })
          }
        />
      )}

      {title && <h2 data-testid="DisplayItems-Title">{title}</h2>}

      {showFilterControls && filterComponent && showHeaders && (
        <span data-testid="DisplayItems-CustomFilterComponent">
          {typeof filterComponent === "function"
            ? filterComponent(currentFilter)
            : filterComponent}
        </span>
      )}

      {showFilterControls && !filterComponent && showHeaders && (
        <span data-testid="DisplayItems-DefaultFilterComponent">
          <FilterGroup
            fields={fields}
            savedFilters={tags}
            savedFiltersIsEnabled={showTags}
            onChange={handleFilterChange}
          />
        </span>
      )}

      {enableSorting && showHeaders && (
        <span data-testid="DisplayItems-SortingButton">
          <Button>
            <Icon>sort_by_alpha</Icon>
          </Button>
        </span>
      )}

      {data && type === DisplayItemsPropsType.CARDS && (
        <div data-testid="DisplayItems-Cards">
          {data.map((itm, k) => (
            <li key={k} data-testid="DisplayItems-Card">
              {showCheckboxes && (
                <Checkbox
                  onChange={(
                    event: React.ChangeEvent<HTMLInputElement>,
                    checked: boolean
                  ): void => selectItem(k, checked)}
                  data-testid="DisplayItems-Checkbox"
                  checked={selectedItems.indexOf(k) > -1}
                />
              )}

              {dataItemComponent ? (
                <span data-testid="DisplayItems-CustomRowComponent">
                  {typeof dataItemComponent === "function"
                    ? dataItemComponent(itm)
                    : dataItemComponent}
                </span>
              ) : (
                <span data-testid="DisplayItems-DefaultRowComponent">
                  <DataCard label={`${itm.firstName} ${itm.lastName}`} />
                </span>
              )}
            </li>
          ))}
        </div>
      )}

      {data && type === DisplayItemsPropsType.TABLE && (
        <Table data-testid="DisplayItems-Table">
          <TableHead>
            {showCheckboxes && (
              <TableCell key="checkbox">
                <Checkbox
                  onChange={(
                    event: React.ChangeEvent<HTMLInputElement>,
                    checked: boolean
                  ): void => selectAll(checked)}
                  data-testid="DisplayItems-Checkbox"
                />
              </TableCell>
            )}

            {fields.map((itm, colKey) => {
              return (
                <TableCell key={colKey} data-testid="DisplayItems-TableColumn">
                  {itm.label}
                </TableCell>
              );
            })}
          </TableHead>
          <TableBody>
            {data.map((row, key) => {
              return (
                <TableRow key={key}>
                  {showCheckboxes && (
                    <TableCell key="checkbox">
                      <Checkbox
                        onChange={(
                          event: React.ChangeEvent<HTMLInputElement>,
                          checked: boolean
                        ): void => selectItem(key, checked)}
                        data-testid="DisplayItems-Checkbox"
                        checked={selectedItems.indexOf(key) > -1}
                      />
                    </TableCell>
                  )}
                  {fields.map((itm, cellKey) => {
                    return (
                      <TableCell key={cellKey}>
                        {displayFieldValue(row, itm)}
                      </TableCell>
                    );
                  })}
                </TableRow>
              );
            })}
          </TableBody>
        </Table>
      )}

      {showPagination && (
        <span data-testid="DisplayItems-Pagination">
          Pagination Controls Here
        </span>
      )}

      {selectedItems.length > 0 && !bulkActionsComponent && (
        <BulkSelectedActions
          data={data.filter((itm, k) => selectedItems.indexOf(k) > -1)}
          showActionButtons={Boolean(bulkActions.length)}
          actionButtons={bulkActions}
        />
      )}
      {selectedItems.length > 0 && bulkActionsComponent && (
        <span data-testid="BulkSelectedActions-Custom">
          {typeof bulkActionsComponent === "function"
            ? bulkActionsComponent({
                data: data.filter((itm, k) => selectedItems.indexOf(k) > -1),
              })
            : bulkActionsComponent}
        </span>
      )}
    </div>
  );
};

DisplayItems.defaultProps = {
  type: DisplayItemsPropsType.CARDS,
  loading: false,
  showbulkActions: false,
  showCheckboxes: false,
  showFilterControls: true,
  showAlphabetFilter: false,
  showTags: false,
  showHeaders: true,
  showPagination: false,
  enableSorting: false,
};

export default DisplayItems;
