// @flow
import React, { useCallback, useMemo } from 'react';
import { v4 } from 'uuid';
import { FieldLabel } from '../../typography/field-label';
import type { SelectProps } from './select.proptypes';
import { FormSelect } from './select.css-rules';
import { HideAccessibly, Box } from '../../../primitives';

const generateId = ({ id, prefix }: {| id?: string, prefix: string |}) => {
  return id === undefined ? `${prefix}-${v4()}` : id;
};

const noop = () => {};

export const Select = ({
  children,
  disabled = false,
  error,
  className,
  placeholder,
  value,
  onBlur = noop,
  onFocus = noop,
  large,
  label,
  hideLabel = false,
  id,
  name,
  onChange,
  spacing,
  shrink,
  grow,
  basis,
  focusOnMount,
  'data-qa': dataQa,
  'data-cy': dataCy,
  ...props
}: SelectProps) => {
  const handleChange = useCallback(
    (event) => {
      const newValue = event.target.value;
      onChange(newValue === 'UNDEFINED' ? undefined : newValue);
    },
    [onChange],
  );
  const formSelectId = useMemo(() => generateId({ id, prefix: 'select' }), [
    id,
  ]);

  return (
    <Box
      stacked="column"
      className={className}
      {...{
        // $FlowFixMe upcast
        spacing,
        shrink,
        grow,
        basis,
      }}
      data-cy={dataCy}
      data-qa={dataQa}
      id={id}
      {...props}
    >
      {label !== undefined &&
        (hideLabel ? (
          <HideAccessibly>
            <FieldLabel htmlFor={formSelectId} large={large}>
              {label}
            </FieldLabel>
          </HideAccessibly>
        ) : (
          <FieldLabel htmlFor={formSelectId} large={large}>
            {label}
          </FieldLabel>
        ))}

      <FormSelect
        large={large}
        disabled={disabled}
        error={error}
        value={value == null && placeholder != null ? 'UNDEFINED' : value}
        onBlur={onBlur}
        onChange={handleChange}
        onFocus={onFocus}
        id={formSelectId}
        name={name}
        autoFocus={focusOnMount}
        data-qa={dataQa}
        data-cy={dataCy}
      >
        {placeholder != null ? (
          <option value="UNDEFINED">{placeholder}</option>
        ) : null}
        {children}
      </FormSelect>
    </Box>
  );
};

Select.displayName = 'Select';
