import React, { Component } from 'react';
import ReactSelect from 'react-select';
import { Props as ReactSelectProps } from 'react-select/lib/Select';
import { typeHelpers } from '../../shared';
import { withTheme, ThemeInterface } from '../../styles';
import { inputs } from '../../styles/utils';
// import { MenuList } from './MenuList';
import { Option } from './Option';
import { DropdownIndicator } from './DropdownIndicator';

export type variants = 'primary';

interface Props<OptT extends any = any>
  extends typeHelpers.Omit<
    ReactSelectProps<OptT>,
    'theme' | 'onChange' | 'onBlur'
  > {
  theme: ThemeInterface;
  onChange: (value: OptT['value']) => void;
  onBlur: () => void;
  variant: variants;
  name?: string;
  disabledOptionText?: string;
}

export interface OptionType {
  value: any;
  label: any;
}

const getStyles = (theme: ThemeInterface, variant: variants) => {
  const inputsStyles = inputs({ theme });

  return {
    primary: {
      container: (styles: any) => ({
        ...styles,
        minHeight: inputsStyles.height,
        minWidth: '7rem',
      }),
      control: (styles: any, state: any) => {
        return {
          ...styles,
          borderRadius: theme.radii[1],
          boxShadow: 'none',
          borderColor: theme.colors.placeholder,
          ...(state.isFocused && {
            borderColor: theme.colors.brandMain,
            '&:hover': {
              borderColor: theme.colors.brandMain,
            },
          }),
        };
      },
      valueContainer: (styles: any) => ({
        ...styles,
        paddingLeft: '14px',
        fontSize: theme.fontSizes[1],
        minHeight: inputsStyles.height,
      }),
      dropdownIndicator: (styles: any) => ({
        ...styles,
        paddingRight: '16px',
        color: theme.colors.placeholder,
      }),
      menu: (styles: any) => ({
        ...styles,
        minWidth: '20rem',
      }),
    },
    ghost: {
      container: (styles: any) => ({
        ...styles,
        minWidth: '100%',
      }),
      control: (styles: any, state: any) => {
        return {
          ...styles,
          boxShadow: 'none',
          border: 'none',
        };
      },
      valueContainer: (styles: any) => ({
        ...styles,
        paddingRight: 0,
        paddingLeft: 0,
        fontSize: theme.fontSizes[1],
      }),
      dropdownIndicator: (styles: any) => ({
        ...styles,
        paddingRight: 0,
        color: theme.colors.placeholder,
        '&:hover': {
          color: theme.colors.brandMain,
        },
      }),
      menu: (styles: any) => ({
        ...styles,
        minWidth: '20rem',
      }),
    },
  }[variant];
};

class SelectPrimitiveBase extends Component<Props> {
  public static defaultProps = {
    isClearable: false,
    variant: 'primary',
    onBlur: () => {},
  };

  public handleChange = (value?: OptionType | OptionType[] | null) => {
    const { onChange, onBlur } = this.props;

    if (!value) {
      onChange(value);
    } else {
      const result = Array.isArray(value)
        ? value.map(option => option.value)
        : value.value;
      onChange(result);
    }

    onBlur();
  };

  public render() {
    const {
      theme,
      variant,
      name,
      onChange,
      value,
      options,
      components,
      styles,
      inputRef,
      ...otherProps
    } = this.props;

    return (
      <ReactSelect
        inputId={name}
        ref={inputRef}
        inputRef={inputRef}
        innerRef={inputRef}
        name={name}
        styles={{ ...getStyles(theme, variant), ...styles }}
        components={{
          IndicatorSeparator: null,
          ClearIndicator: null,
          DropdownIndicator,
          Option,
          ...components,
          //...(options.length > 100 && { MenuList }), // If more than 50 options, virtualize
        }}
        backspaceRemovesValue={false}
        isSearchable={false}
        onChange={this.handleChange}
        menuPlacement="auto"
        menuPortalTarget={document.body}
        options={options}
        value={
          value
            ? Array.isArray(value)
              ? value
              : options.find((option: OptionType) => option.value === value)
            : undefined
        }
        {...otherProps}
      />
    );
  }
}

const ThemedSelectPrimitive = withTheme(SelectPrimitiveBase);

export const Select = Object.assign(ThemedSelectPrimitive, {
  defaultProps: SelectPrimitiveBase.defaultProps,
});

export type SelectProps = React.ComponentProps<typeof Select>;
