import React from "react";
import { DropdownBox } from "../dropdown";
import {
  VirtualizedList as List,
  VirtualizedListProps,
  VirtualizedListItem,
} from "../list/VirtualizedList";
import { SelectOptionWithGroup } from "../select/SelectOption";
import { StyledProps } from "../_type";
import { SimulateSelectProps } from "../select";
import { useConfig } from "../util";
import { useIsomorphicLayoutEffect } from "../_util/use-isomorphic-layout-effect";

export interface TagSelectBoxProps extends StyledProps {
  items: VirtualizedListItem<SelectOptionWithGroup>[];
  width: number;
  onChange: (
    value: string,
    context: { event: React.MouseEvent; option: SelectOptionWithGroup }
  ) => void;
  scheduleUpdate: () => void;
  tips: React.ReactNode;
  currentIndex: number;
  listRef: VirtualizedListProps["virtualizedRef"];
  onScrollBottom: VirtualizedListProps["onScrollBottom"];
  footer: React.ReactNode;
}

export function TagSelectBox({
  listRef,
  items,
  onChange,
  width,
  scheduleUpdate,
  className,
  style = {},
  currentIndex,
  onScrollBottom,
  footer,
}: TagSelectBoxProps) {
  useIsomorphicLayoutEffect(() => {
    scheduleUpdate();
  }, [scheduleUpdate, items]);

  const { classPrefix } = useConfig();

  const count = items.length;
  if (count === 0) {
    return null;
  }

  const hasGroup = !!items.find(item => item.type === "group");

  const boxStyle = { ...style, width };

  return (
    <DropdownBox
      preventMouseDown
      onClick={e => e.stopPropagation()}
      className={className}
      style={boxStyle}
      footer={footer}
    >
      <List
        containerStyle={boxStyle}
        containerClassName={className}
        virtualizedRef={listRef}
        type={hasGroup ? "option-group" : "option"}
        items={items.map((item, index) => {
          if (item.type === "option") {
            const { option } = item;
            return {
              ...item,
              props: {
                disabled: option.disabled,
                current: currentIndex % count === index,
                onClick: event => {
                  onChange(option.value, {
                    event,
                    option,
                  });
                },
                tooltip: option.tooltip,
                className:
                  hasGroup && !option.groupKey
                    ? `${classPrefix}-list__item--single`
                    : "",
              },
            };
          }
          return item;
        })}
        onScrollBottom={onScrollBottom}
      />
    </DropdownBox>
  );
}

TagSelectBox.displayName = "TagSelectBox";

export function getListItems({
  tips,
  options,
  groups,
}: Pick<
  SimulateSelectProps,
  "tips" | "options" | "groups"
>): VirtualizedListItem<SelectOptionWithGroup>[] {
  const items: VirtualizedListItem<SelectOptionWithGroup>[] = [];
  if (tips) {
    items.push({ type: "tips", key: "__tips", text: tips });
  }

  options.forEach((option, index) => {
    if (
      option.groupKey &&
      (index === 0 || option.groupKey !== options[index - 1].groupKey)
    ) {
      items.push({
        type: "group",
        key: `${option.groupKey}-${option.value}`,
        text: groups[option.groupKey],
      });
    }
    items.push({
      type: "option",
      key: option.value,
      text: typeof option.text === "undefined" ? option.value : option.text,
      option,
    });
  });
  return items;
}
