// @flow
import React, { type ComponentType, useCallback, useState } from 'react';
import styled, { withTheme } from 'styled-components';
import randomstring from 'randomstring';
import { remove, concat } from 'lodash';
import type { SelectorProps } from './selector.proptypes';
import { getPaletteColor } from '../../../mixins/branding';
import { FieldLabel } from '../../typography/field-label';
import { SelectorContextProvider } from './selector-context';
import { HideAccessibly } from '../../../primitives/hide-accessibly';

/**
 * TODO: Add support from RadioOptions as `large` configuration
 * TODO: Add support for free-form, like RadioOptions has (required for gender select)
 * TODO: Delete the RadioOptions in the Graveyard
 * TODO: Rename component to RadioOptions after ☝️
 */

const SelectorContainer = styled.div`
  && {
    border: 1px solid ${getPaletteColor('greyscale-light')};
    border-radius: 6px;
  }

  & > *:first-child {
    border-radius: 6px 6px 0 0;
  }

  & > *:only-child {
    border-radius: 6px;
  }

  && > * {
    border-bottom: 1px solid ${getPaletteColor('greyscale-light')};
  }

  && > *:last-child {
    border-bottom: 0;
    border-radius: 0 0 6px 6px;
  }
`;

export const SizeContext = React.createContext<
  $PropertyType<SelectorProps, 'size'>,
>('md');

const _Selector = ({
  label,
  hideLabel = false,
  children,
  size,
  labelSpacing = ['pt3', 'pb1'],
  stateful,
  name,
  onChange,
  type = 'radio',
}: SelectorProps) => {
  const [managedValue, setManagedValue] = useState();

  const handleChange = useCallback(
    (event) => {
      if (!stateful) {
        onChange(event.target.value);
        return;
      }

      let newValue = event.target.value;

      if (type === 'checkbox' && Array.isArray(managedValue)) {
        if (managedValue.includes(newValue)) {
          // Removing
          newValue = remove(managedValue, (v) => v !== newValue);
        } else {
          // Adding
          newValue = concat(managedValue, newValue);
        }
      }

      setManagedValue(newValue);
      onChange(newValue);
    },
    [managedValue, onChange, stateful, type],
  );

  const selectorId = `selector-${randomstring.generate(5)}`;

  return (
    <SizeContext.Provider value={size}>
      {hideLabel ? (
        <HideAccessibly>
          <FieldLabel htmlFor={selectorId} spacing={labelSpacing}>
            {label}
          </FieldLabel>
        </HideAccessibly>
      ) : (
        <FieldLabel htmlFor={selectorId} spacing={labelSpacing}>
          {label}
        </FieldLabel>
      )}
      <SelectorContextProvider
        value={{ stateful, name, onChange: handleChange, managedValue, type }}
      >
        <SelectorContainer id={selectorId}>{children}</SelectorContainer>
      </SelectorContextProvider>
    </SizeContext.Provider>
  );
};

export const Selector: ComponentType<SelectorProps> = withTheme(_Selector);

Selector.displayName = 'Selector';
