import React, { useCallback } from 'react';
import { Sort } from 'utils/sort';
import { TableRow } from './table-row';
import { ExpandedRow } from './expanded-row';
import { STableBody } from '../../s-components/table/s-table-body';
import { BodyContent, TableContent, TableElementId } from './constants';
import { bem } from 'utils/bem';
import { TableTheme } from 'app/theme/table';
import { TableInfiniteLoader } from './table-infinite-loader';

export interface TableBodyProps<BodyType extends BodyContent, SortField extends string> {
  bodyContent: BodyType[];
  headerContent: TableContent<BodyType, SortField>[];
  onCheckboxChange?(isChecked: boolean, id: TableElementId): void;
  onExpanded?(isExpanded: boolean, item: BodyContent): void;
  sort: Sort<SortField>;
  isCheckable?: boolean;
  isExpandable?: boolean;
  renderExpandedRow?: (content: BodyType) => React.ReactNode;
  hasStickyColumns?: boolean;
  expandedIds: TableElementId[];
  checkedIds: TableElementId[];
  theme: TableTheme;
  shouldDisableExpandForRow?: (rowData: BodyType) => boolean;
  withoutRoundCorners?: boolean;
  isScrollable?: boolean;
  isInfiniteLoading?: boolean;
}

const classes = bem('table-body');

export const TableBody = <BodyType extends BodyContent, SortField extends string>(
  props: TableBodyProps<BodyType, SortField>
) => {
  const {
    bodyContent,
    headerContent,
    expandedIds,
    checkedIds,
    onCheckboxChange,
    sort,
    isCheckable,
    isExpandable,
    isScrollable,
    theme,
    onExpanded,
    renderExpandedRow,
    hasStickyColumns,
    shouldDisableExpandForRow,
    withoutRoundCorners,
    isInfiniteLoading = false,
  } = props;
  const getIsExpanded = useCallback((id: TableElementId) => expandedIds.includes(id), [expandedIds]);
  const getIsChecked = useCallback((id: TableElementId) => checkedIds.includes(id), [checkedIds]);
  return (
    <STableBody tableTheme={theme} withoutRoundCorners={withoutRoundCorners}>
      {bodyContent.map((rowData, index) => {
        const isExpanded = getIsExpanded(rowData.id);
        const isChecked = getIsChecked(rowData.id);
        const isEven = index % 2 === 0;
        return (
          <React.Fragment key={rowData.id}>
            <TableRow
              index={index}
              headerContent={headerContent}
              sort={sort}
              theme={theme}
              rowData={rowData}
              isExpandable={isExpandable}
              isCheckable={isCheckable}
              onExpanded={onExpanded}
              onCheckboxChange={onCheckboxChange}
              isExpanded={isExpanded}
              isChecked={isChecked}
              hasStickyColumns={hasStickyColumns}
              shouldDisableExpandForRow={shouldDisableExpandForRow}
            />
            <ExpandedRow
              headerContent={headerContent}
              isExpanded={isExpanded}
              renderExpandedRow={renderExpandedRow}
              rowData={rowData}
              isEven={isEven}
              theme={theme}
              sort={sort}
              hasStickyColumns={hasStickyColumns}
              isCheckable={isCheckable}
            />
          </React.Fragment>
        );
      })}
      {isInfiniteLoading && (
        <TableInfiniteLoader colSpan={isExpandable || isCheckable ? headerContent.length + 1 : headerContent.length} />
      )}
      {/*This element is required for elements to have fixed height when the table is full height*/}
      {isScrollable && (
        <tr>
          <td className={classes('bottom-spacer')} />
        </tr>
      )}
    </STableBody>
  );
};
