import { useEffect, useState } from 'react';
import { Data } from '../../../types';
import { DynamicListColumn } from '../DynamicDataList.model';

/**
 * Generates a combined string of all columns.columnSize values, to be used as CSS value
 * Also produces property key which is used for positioning
 * @param columns The list of columns that should be used
 * @returns a string that consists of defined column sizes and a position key that maps to a data property
 */
export const useColumnDefs = function <T extends Data>(
  columns: DynamicListColumn<T>[],
  allowReordering: boolean,
  allowNewData: boolean,
  allowEditing: boolean,
  allowRowDragging: boolean,
  positionKey?: keyof T,
  showInlineMenu?: boolean,
): {
  readonly columnSizes: string;
  readonly showPositionColumn: boolean;
  readonly showActionColumn: boolean;
  resetColumnSizes: () => void;
  setColumnSizes: (newColumnSizes: string) => void;
} {
  const [isResized, setIsResized] = useState<boolean>(false);

  const [orgColumnSizes, setOrgColumnSizes] = useState<string>(
    calculateColumnSizes(
      columns,
      allowReordering,
      allowRowDragging,
      positionKey,
      allowNewData || showInlineMenu || allowEditing,
    ),
  );

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

  useEffect(() => {
    setOrgColumnSizes(
      calculateColumnSizes(
        columns,
        allowReordering,
        allowRowDragging,
        positionKey,
        allowNewData || showInlineMenu || allowEditing,
      ),
    );
    if (!isResized) {
      setColumnSizes(orgColumnSizes);
    }
  }, [
    allowEditing,
    allowNewData,
    allowReordering,
    allowRowDragging,
    columns,
    isResized,
    orgColumnSizes,
    positionKey,
    showInlineMenu,
  ]);

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

  return {
    columnSizes,
    showPositionColumn: allowReordering && positionKey !== undefined,
    showActionColumn: (allowNewData || showInlineMenu) ?? false,
    resetColumnSizes,
    setColumnSizes: (newColumnSizes: string) => {
      const positionColumn = getPositionColumnWidth(
        allowReordering,
        allowRowDragging,
        positionKey,
      );

      setIsResized(true);
      setColumnSizes(`${positionColumn} ${newColumnSizes}`.trim());
    },
  } as const;
};

function calculateColumnSizes<T extends Data>(
  columns: DynamicListColumn<T>[],
  allowReordering: boolean,
  allowRowDragging: boolean,
  positionKey?: keyof T,
  showActionColumn?: boolean,
): string {
  const positionColumn = getPositionColumnWidth(
    allowReordering,
    allowRowDragging,
    positionKey,
  );
  let actionColumn = '';

  const columnDefinition = columns
    .filter((columns) => columns.propertyName !== positionKey) // do not allow a column to be created for 'position'
    .reduce((prev, current) => `${prev} ${current.size ?? '1fr'}`, '')
    .trim();

  if (showActionColumn) {
    actionColumn = '50px';
  }

  return `${positionColumn} ${columnDefinition} ${actionColumn}`.trim();
}

function getPositionColumnWidth<T extends Data>(
  allowReordering: boolean,
  allowRowDragging: boolean,
  positionKey?: keyof T,
): string {
  // only show position column if allowReordering is true and the positionKey exists
  if (allowReordering && positionKey !== undefined) {
    if (allowRowDragging === true) {
      return '100px';
    } else {
      return '50px';
    }
  }

  return '';
}
