import React, { HTMLAttributes, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useSize } from '../../hooks';
import { SilkeVirtualRow } from './silke-virtual-row';
import styles from './silke-virtual.scss';

type SilkeVirtualGridProps<T> = {
  cell?: [width: number, height: number];
  items: T[];
  children: (item: T, index: number) => React.ReactNode;
  rowAttrs?: (rowIndex: number) => Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
} & Omit<HTMLAttributes<HTMLDivElement>, 'children'>;

export function SilkeVirtualGrid<T>({
  items,
  cell,
  children,
  rowAttrs,
  className,
  style,
  ...rest
}: SilkeVirtualGridProps<T>) {
  let cl = styles.grid;
  if (className) cl += ' ' + className;
  const [columns, setColumns] = useState(1);
  const ref = useRef<HTMLDivElement>(null);
  const [width, height] = cell || [32, 32];

  useSize(ref, (entry) => {
    const newColumns = Math.floor(entry.contentRect.width / width);
    if (newColumns !== columns && newColumns > 0) setColumns(newColumns);
  });

  useLayoutEffect(() => {
    const el = ref.current;
    if (el) {
      setColumns(Math.max(Math.floor(el.getBoundingClientRect().width / width), 1));
    }
  }, [width]);

  const list = useMemo(() => {
    const list: any[] = [];
    if (columns === 0) return list;
    const rows = Math.ceil(items.length / columns);
    for (let i = 0; i < rows; i++) {
      const start = i * columns;
      const end = Math.min(start + columns, items.length);
      list.push(
        <SilkeVirtualRow
          indexOffset={i}
          items={items.slice(start, end)}
          rowAttrs={rowAttrs}
          key={i}
        >
          {children}
        </SilkeVirtualRow>,
      );
    }
    return list;
  }, [columns, items, children, rowAttrs]);

  return (
    <div
      className={cl}
      style={{ ...style, '--cell-height': height + 'px' } as any}
      ref={ref}
      {...rest}
    >
      {list}
    </div>
  );
}
