// @flow
import React from 'react';
import type { ComponentType } from 'react';
import { compose, withContext, withHandlers, withState } from 'recompose';
import styled, { withTheme } from 'styled-components';
import { remove, concat } from 'lodash';
import type { ThemeProps } from '../../../types';
import type { SelectorProps } from './selector.proptypes';
import { selectorProptypes, selectorContextTypes } from './selector.proptypes';
import { getPaletteColor } from '../../../mixins/branding';
import { FieldLabel } from '../../typography/field-label';

/**
 * 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 ☝️
 * TODO: Remove label that's inside of this component OR accessibly-hide teh label
 */

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

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

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

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

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

const withManagedValueState = withState(
  'managedValue',
  'setManagedValue',
  ({ value }) => value || undefined,
);

const withChangeHandler = withHandlers(() => ({
  onChangeHandler: ({
    setManagedValue,
    onChange,
    managedValue,
    type,
    stateful,
  }) => event => {
    if (!stateful) {
      onChange(event.target.value);
      return;
    }

    let newValue = event.target.value;

    if (type === 'checkbox') {
      const shouldRemove =
        Array.isArray(managedValue) && managedValue.includes(newValue);

      if (shouldRemove) {
        // Removing
        newValue = remove(managedValue, v => v !== newValue);
      } else {
        // Adding
        newValue = concat(managedValue || [], newValue);
      }
    }

    setManagedValue(newValue);
    onChange(newValue);
  },
}));

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

const withSelectorContext = withContext(selectorContextTypes, props => ({
  stateful: props.stateful,
  name: props.name,
  onChange: props.onChangeHandler,
  managedValue: props.managedValue,
  type: props.type !== undefined ? props.type : 'radio',
}));

const _Selector = ({
  label,
  children,
  size,
  labelSpacing = ['pt3', 'pb1'],
}: SelectorProps & ThemeProps) => (
  <SizeContext.Provider value={size}>
    {label != null && <FieldLabel spacing={labelSpacing}>{label}</FieldLabel>}
    <SelectorContainer>{children}</SelectorContainer>
  </SizeContext.Provider>
);

export const Selector: ComponentType<SelectorProps> = compose(
  withManagedValueState,
  withChangeHandler,
  withSelectorContext,
  withTheme,
)(_Selector);

Selector.displayName = 'Selector';
Selector.propTypes = selectorProptypes;
