import { useEffect, useState } from 'react';
import { Data } from '../../types';
import { Column, ListSelectMode } from './List.model';

/**
 * Generates a combined string of all columns.columnSize values, to be used as CSS value
 * @param columns The list of columns that should be used
 * @returns a string of all column sizes of the array, combined
 */
const getColumnsSizeDefinition = function <T extends Data>(
  columns: Column<T>[],
  showActionButton: boolean,
  selectMode: ListSelectMode,
  showInlineMenu: boolean,
): string {
  const columnSizeDefinition = columns.map((column) => column.size ?? '1fr');

  const hasActionsColumn = hasActionColumn(
    selectMode,
    showActionButton,
    showInlineMenu,
  );

  if (hasActionsColumn) {
    columnSizeDefinition.push(
      getActionsColumnSizePx(showInlineMenu, showActionButton),
    );
  }

  return columnSizeDefinition.join(' ');
};

const getActionsColumnSizePx = (...enableActions: boolean[]): string => {
  const enabledActionsCount = enableActions.filter(
    (actionEnabled) => actionEnabled,
  ).length;

  const defaultActionSizePx = 50;
  const defaultActionsRawGapPx = 8;
  const calculateMultiActionsColumnSizePx = (actionsCount: number): number => {
    return (
      defaultActionSizePx * actionsCount +
      defaultActionsRawGapPx * (actionsCount - 1)
    );
  };

  const sizePx =
    enabledActionsCount > 1
      ? calculateMultiActionsColumnSizePx(enabledActionsCount)
      : defaultActionSizePx;

  return `${sizePx}px`;
};

/**
 * Covers the concern of managing the column sizes for the list component
 * @param columns input definition of columns
 * @param showActionButton whether the action button is shown
 * @param selectMode current select mode
 * @param showInlineMenu whether the inline menu is shown
 * @returns an object containing the columnSizes (CSS grid-template-columns),
 *          a reset function (to reset to the initial column sizes)
 *          and a setter function (to update the column sizes)
 */
export const useColumnsSize = <T extends Data>(
  columns: Column<T>[],
  showActionButton: boolean,
  selectMode: ListSelectMode,
  showInlineMenu: boolean,
): {
  columnSizes: string;
  resetColumnSizes: () => void;
  setColumnSizes: (newColumnSizes: string) => void;
  hasActionColumn: boolean;
} => {
  const [isResized, setIsResized] = useState<boolean>(false);

  const [orgColumnSizes, setOrgColumnSizes] = useState<string>(
    getColumnsSizeDefinition(
      columns,
      showActionButton,
      selectMode,
      showInlineMenu,
    ),
  );

  const [columnSizes, setColumnSizes] = useState<string>(orgColumnSizes);

  useEffect(() => {
    setOrgColumnSizes(
      getColumnsSizeDefinition(
        columns,
        showActionButton,
        selectMode,
        showInlineMenu,
      ),
    );
    if (!isResized) {
      setColumnSizes(orgColumnSizes);
    }
  }, [
    columns,
    isResized,
    orgColumnSizes,
    selectMode,
    showActionButton,
    showInlineMenu,
  ]);

  const resetColumnSizes = (): void => {
    setColumnSizes(orgColumnSizes);
    setIsResized(false);
  };

  return {
    columnSizes,
    resetColumnSizes,
    setColumnSizes: (newColumnSizes: string) => {
      setIsResized(true);
      setColumnSizes(newColumnSizes);
    },
    hasActionColumn: hasActionColumn(
      selectMode,
      showActionButton,
      showInlineMenu,
    ),
  };
};
function hasActionColumn(
  selectMode: ListSelectMode,
  showActionButton: boolean,
  showInlineMenu: boolean,
): boolean {
  return (
    selectMode !== ListSelectMode.None || showActionButton || showInlineMenu
  );
}
