import clsx from 'clsx';
import React, { PropsWithChildren } from 'react';
import { useResize } from '../../../hooks/useResize/useResize';
import { Data } from '../../../types/data';
import { Column, SortData } from '../List.model';
import { ListCheckBox } from '../ListCheckBox/ListCheckBox';
import { ColumnLabel } from './ColumnLabel/ColumnLabel';
import classes from './ListHeader.scss';

export interface ListHeaderProps<T extends Data> {
  /** Column definitions */
  columns: Column<T>[];
  /** Sizes of each column */
  columnSizes: string;
  /** Spacing between columns */
  columnGap: string;
  /** Header row height */
  rowHeight: string;
  /** Size of the checkbox */
  actionSize: string;
  /** Horizontal alignment of text */
  horizontalTextAlign: 'left' | 'right' | 'center';
  /** Vertical alignment of text */
  verticalTextAlign: 'start' | 'center' | 'end';
  /** Whether or not the item is selected (default: false) */
  itemSelected?: boolean;
  /** Defines how the list data should be sorted */
  sortData?: SortData<T>;
  /** Defines whether the create button will be rendered (default: true) */
  showCreateButton?: boolean;
  /** Defines whether a checkbox for each item should be rendered (default: true) */
  showItemCheckbox?: boolean;
  /** Whether or not the checkbox needs to be disabled (default: false) */
  isCheckboxDisabled?: boolean;
  /** Raised when the header checkbox has been changed. Checked state is sent back. */
  onCheckboxToggled?: (checked: boolean) => void;
  /** Callback to emit when a sort event occurs. Name of the property and order of the direction are sent back. */
  onSortChanged?: (sort: SortData<T>) => void;
  /** CSS Class name for additional styles */
  className?: string;
  /** called when the column sizes should be reset */
  onResetColumnSizes: () => void;
  /** called when the column sizes should be updated */
  onColumnSizesChanged: (columnSizes: string) => void;
  /** Whether or not the list has an action column */
  hasActionColumn: boolean;
}

/**
 * Renders the headers for the list component
 * @example
 * <ListHeader
 *  columns={[{propertyName: 'id', size: '1fr', label: 'Id'}]}
 *  columnSizes={'1fr'}
 *  columnGap={'5px'}
 *  rowHeight={'44px'}
 *  horizontalTextAlign={'left'}
 *  verticalTextAlign={'center'}
 * />
 */
export const ListHeader = <T extends Data>({
  columns,
  columnSizes,
  columnGap,
  rowHeight,
  actionSize,
  horizontalTextAlign,
  verticalTextAlign,
  itemSelected = false,
  sortData,
  showItemCheckbox = true,
  isCheckboxDisabled = false,
  onCheckboxToggled,
  onSortChanged,
  className = '',
  onResetColumnSizes,
  onColumnSizesChanged,
  hasActionColumn,
}: PropsWithChildren<ListHeaderProps<T>>): JSX.Element => {
  const customStyles = {
    gridAutoRows: rowHeight,
    gridTemplateColumns: columnSizes,
    gridColumnGap: columnGap,
    justifyItems: horizontalTextAlign,
    alignItems: verticalTextAlign,
  } as React.CSSProperties;

  const { cols, mouseDown, ResizeIndicator } = useResize(
    columns,
    onColumnSizesChanged,
  );

  return (
    <>
      {ResizeIndicator}
      <div
        className={clsx(classes.container, 'list-header-container', className)}
        style={customStyles}
        data-test-id="list-header"
      >
        {columns.map((column, i) => (
          <div
            key={column.key ?? (column.propertyName as string)}
            ref={cols[i].ref}
            className={clsx(classes.columnLabel)}
          >
            <ColumnLabel<T>
              propertyName={column.propertyName}
              label={column.label ?? (column.propertyName as string)}
              sortable={column.sortable}
              columnSortKeys={column?.columnSortKeys}
              sortData={sortData}
              onSortChanged={onSortChanged}
            />
            <div
              onMouseDown={
                !column.disableResizing
                  ? (e) => {
                      e.preventDefault();
                      mouseDown(i);
                    }
                  : undefined
              }
              onDoubleClick={() => onResetColumnSizes()}
              className={clsx(classes.resizeHandle, {
                [classes.resizeHandleDisabled]: column.disableResizing,
              })}
            />
          </div>
        ))}
        {hasActionColumn && (
          <div
            ref={cols[cols.length - 1].ref}
            className={clsx(classes.columnLabel)}
          >
            {showItemCheckbox && (
              <ListCheckBox
                height={actionSize}
                width={actionSize}
                isChecked={itemSelected}
                isDisabled={isCheckboxDisabled}
                onCheckBoxToggled={onCheckboxToggled}
              />
            )}
          </div>
        )}
      </div>
    </>
  );
};
