import { Box, Text, UseInput } from "./Ink";
import React, { useMemo, useState } from "react";

type SelectableListProps<Item> = {
  height: number;
  width: number;
  items: Array<Item>;
  onItemSelected: (item: Item) => void;
  item: {
    key: (item: Item) => string;
    label: (item: Item) => string;
  };
  selected?: Array<Item>;

  useInput: UseInput;
};

export const SelectableList = <Item,>({
  height,
  width,
  item: { key, label },
  items,
  onItemSelected,
  selected = [],
  useInput,
}: SelectableListProps<Item>) => {
  const scrollMargin = Math.ceil(height / 10);

  const [hoverIndex, setHoverIndex] = useState(0);

  const scrollOffset = useMemo(
    () =>
      hoverIndex > items.length - height
        ? Math.max(items.length - height, 0)
        : hoverIndex > scrollMargin
          ? hoverIndex - scrollMargin
          : 0,
    [hoverIndex, scrollMargin, items],
  );

  const displayedItems = items.slice(scrollOffset, scrollOffset + height);

  useInput((input, key) => {
    if (key.upArrow) {
      const newHoverIndex = Math.max(hoverIndex - 1, 0);
      setHoverIndex(newHoverIndex);
    } else if (key.downArrow) {
      const newHoverIndex = Math.min(hoverIndex + 1, items.length - 1);
      setHoverIndex(newHoverIndex);
    } else {
      if (input === " ") {
        onItemSelected(items[hoverIndex]!);
      }
    }
  });

  return (
    <Box flexDirection="column" height={height} width={width}>
      {displayedItems.map((item, index) => (
        <Text
          key={key(item)}
          color={index === hoverIndex - scrollOffset ? "blue" : "white"}
          bold={selected.includes(item)}
        >
          {selected.includes(item) ? "◉ " : "○ "}
          {label(item)}
        </Text>
      ))}
    </Box>
  );
};
