import React, { FunctionComponent, HTMLAttributes, ReactElement } from 'react';
import { useVirtualGridRepeaterContext } from './VirtualGridRepeaterContext';
import { observer } from 'mobx-react-lite';
import { VirtualItemProps } from './VirtualItem';

function _ForceRenderIndexes({
  children,
  ItemElementType,
  contentsWrapper,
}: {
  children: ReactElement<{ rowIndex: number; columnIndex: number }>[];
  ItemElementType: FunctionComponent<VirtualItemProps>;
  contentsWrapper: (props: {
    contents: ReactElement;
    listAttributes?: HTMLAttributes<HTMLElement>;
  }) => ReactElement;
}) {
  const { state } = useVirtualGridRepeaterContext();

  const {
    gridState: { forceRenderIndexes, listAttributes, itemsToRenderCount },
    gridRef,
    calcGridProps: { columnCount },
  } = state;

  if (process.env.NODE_ENV !== 'production') {
    if (gridRef) {
      if (typeof gridRef._getItemStyle !== 'function') {
        throw new Error(
          'Missing `_getItemStyle()` API from react-window. This is probably a breaking change of react-window, please contact #cairo, thanks!',
        );
      }
    }
  }

  const forceRenderElements =
    gridRef &&
    forceRenderIndexes
      ?.filter((index) => index < itemsToRenderCount)
      ?.map((index) => {
        const rowIndex = Math.floor(index / columnCount);
        const columnIndex = index % columnCount;

        const key = state.itemKeyRecycler({ columnIndex, rowIndex });

        return (
          <ItemElementType
            key={key}
            rowIndex={rowIndex}
            columnIndex={columnIndex}
            style={gridRef._getItemStyle(rowIndex, columnIndex)}
            data={undefined}
          />
        );
      });

  const contents = (
    <>
      {forceRenderElements}
      {forceRenderElements
        ? children.filter(
            ({ props }) =>
              !forceRenderElements.some(
                ({ props: { rowIndex, columnIndex } }) =>
                  rowIndex === props.rowIndex &&
                  columnIndex === props.columnIndex,
              ),
          )
        : children}
    </>
  );

  return contentsWrapper({ contents, listAttributes });
}

export const ForceRenderIndexesObserver = observer(_ForceRenderIndexes);
