// @flow
import React, { useMemo } from 'react';
import { v4 as guid } from 'uuid';
import type {
  ListSelectorProps,
  ListSelectorItem,
} from './list-selector.proptypes';
import { StyledFormList, HoverBox } from './list-selector.css-rules';
import { FieldSet } from '../field-set';
import { CheckBox } from '../check-box';
import { Radio } from '../radio';

type ItemProps<T> = {
  item: ListSelectorItem<T>,
  selectedItemIds: T[],
  multiSelect: boolean,
  name: string,
  onChange: (T[]) => void,
};

const Item = <T>({
  multiSelect,
  item,
  name,
  selectedItemIds,
  onChange,
}: ItemProps<T>) => {
  if (item.isNonOptionRow) {
    return item.label;
  }

  const isSelected = !!selectedItemIds.includes(item.id);
  return multiSelect ? (
    <CheckBox
      justify="space-between"
      spacing="ph2"
      direction="right"
      name={`${name}-${String(item.id)}`}
      selected={isSelected}
      onToggle={() =>
        onChange(
          isSelected
            ? selectedItemIds.filter((id) => id !== item.id)
            : selectedItemIds.concat(item.id).sort(),
        )
      }
      disabled={item.disabled}
    >
      {item.label}
    </CheckBox>
  ) : (
    <Radio
      justify="space-between"
      spacing="ph2"
      direction="right"
      value={String(item.id)}
      name={name}
      selected={isSelected}
      onSelected={() => onChange([item.id])}
      disabled={item.disabled}
    >
      {item.label}
    </Radio>
  );
};

export const ListSelector = <T>({
  name,
  value,
  onChange,
  items,
  label,
  hideLabel = false,
  small = false,
  multiSelect = false,
  ...rest
}: ListSelectorProps<T>) => {
  const defaultedName = useMemo(() => name ?? `list-selector-${guid()}`, [
    name,
  ]);
  return (
    <FieldSet label={label} hideLabel={hideLabel} {...rest}>
      <StyledFormList
        items={items.map((item) => (
          <HoverBox
            key={String(item.id)}
            isDisabled={item.disabled}
            stacked="column"
            align="stretch"
          >
            <Item
              name={defaultedName}
              multiSelect={multiSelect}
              small={small}
              item={item}
              selectedItemIds={value}
              onChange={onChange}
            />
          </HoverBox>
        ))}
      />
    </FieldSet>
  );
};

ListSelector.displayName = 'ListSelector';
