import classNames from 'classnames';
import isEqual from 'lodash/isEqual';
import _get from 'lodash/get';
import React from 'react';
import PropTypes from 'prop-types';
import extend from 'extend';
import BaseSelect from '../BaseSelect';
import optionsFactory, { buildCustomOption } from './options';
import wrap from '../ItemContainerWrapper';

import { KdSelectEntity } from '../KdSelectEntity';
import { itemHandlerCreator } from '../../utils';
import { ADD_CHICKLET, ANY } from '../../constants';

const defaultProps = {
  selectedValuesInitial: [],
  selectBehavior: ADD_CHICKLET,
  isDisabled: false,
  mainSelector: {
    visible: true,
    notSelectedOption: { label: 'Any' },
    optionGroups: [],
  },
  events: {},
  autoComplete: {
    clearTextboxOnSelection: true,
    renderClearTextboxButton: true,
  },
};

const propTypes = {
  theme: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired,
  selectBehavior: PropTypes.string,

  api: PropTypes.shape({
    url: PropTypes.string,
    key: PropTypes.string,
    bearerToken: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  }),

  events: PropTypes.shape({
    onSelect: PropTypes.func,
    onChange: PropTypes.func,
  }),

  mainSelector: PropTypes.shape({
    visible: PropTypes.bool,
    notSelectedOption: PropTypes.shape({
      label: PropTypes.string,
    }),
    selectedOption: PropTypes.shape({
      visible: PropTypes.bool,
      label: PropTypes.string,
    }),
    optionGroups: PropTypes.arrayOf(
      PropTypes.shape({
        label: PropTypes.string,
        options: PropTypes.object,
      })
    ),
  }),
  // private props
  selectedValuesInitial: PropTypes.array,
};

class KdSelectEntityMultiple extends React.Component {
  constructor(props) {
    super(props);
    this.mainSelector = extend(true, {}, { visible: true }, props.mainSelector);
    this.options = this.propBasedOptions();
    this.state = {
      selectedOption: this.options[0],
      selectedValue: '',
    };
  }

  hasSameSelectedValues = (a, b) => {
    const keys = ['options.selectedValuesInitial', 'options.kdFilterModel'];
    if (Array.isArray(a) || Array.isArray(b)) return;

    return keys.every(key => isEqual(_get(a, key), _get(b, key)));
  };

  setSelectedValues = (values, model) => {
    values.forEach(({ value, label }) => {
      const kdFilterOptions = {
        model,
        operator: 'Eq',
        itemHandler: itemHandlerCreator(model.getDataType()),
      };
      this.addItem({ value, label, kdFilterOptions, inputVisible: true, silent: true });
    });
  };

  addItem = ({ value, label, kdFilterOptions, inputVisible = null, silent = false }, callback) => {
    const { events: { onChange, onSelect } } = this.props;
    const remove =
      this.props.isChickletNone &&
      this.Autocomplete &&
      this.Autocomplete.setInputValue.bind(this.Autocomplete);
    const event = () => {
      const data = {
        value,
        label,
        model: kdFilterOptions.model,
        ...kdFilterOptions.model.getFilterItemValue(),
      };
      onChange && onChange({ data });
      onSelect && onSelect({ data });
      callback && callback();
    };
    if (!inputVisible) {
      this.Autocomplete.setInputValue();
    }
    this.props.onItemAdded(
      {
        value,
        remove,
        kdFilterOptions,
        chickletLabel: label,
        option: value,
        inputVisible,
      },
      !silent && event
    );
  };

  getSelected = () => {
    const selected = this.options.filter(o => o.isSelected)[0];
    return selected || this.options[0];
  };

  selectDefaultOption = () => {
    if (this.options[0]) {
      this.setState({ selectedOption: this.getSelected() }, () =>
        this.props.onOptionSelected(this.state.selectedOption.id)
      );
    }
  };

  componentWillMount() {
    this.selectDefaultOption();
  }

  // componentWillReceiveProps(nextProps) {
  //   const customOptions = this.mainSelector.optionGroups;
  //   const newCustomOptions = nextProps.mainSelector.optionGroups;
  //   if (!isEqualWith(customOptions, newCustomOptions, this.hasSameSelectedValues)) {
  //     this.mainSelector = nextProps.mainSelector;
  //     this.props.onClearChicklets();
  //     this.options = this.propBasedOptions();
  //     this.selectDefaultOption();
  //   }
  // }

  propBasedOptions() {
    const { notSelectedOption, optionGroups } = this.mainSelector;
    const initialOptions = [];

    if (notSelectedOption) {
      const { label, selected } = notSelectedOption;
      initialOptions.push(optionsFactory.create(ANY, label, selected));
    }

    return initialOptions.concat(
      optionGroups.map(({ label, options, selected }, index) => {
        const newLabel = label || options.kdFilterModel.getEntityType();
        return buildCustomOption({ label: newLabel, modelOptions: options, key: index, selected });
      })
    );
  }

  onSelectChange = ({ target }) => {
    const selectedOption = this.options.find(option => option.id === target.value);

    this.props.onClearChicklets();

    this.setState(
      {
        selectedOption,
        selectedValue: selectedOption.selectedLabel,
      },
      () => this.props.onOptionSelected(this.state.selectedOption.id)
    );
  };

  optionHelper() {
    if (this.anySelected()) {
      return null;
    }

    const { selectedOption: { modelOptions, id } } = this.state;
    const {
      theme,
      selectBehavior,
      onItemAdded,
      onItemRemoved,
      onOptionSelected,
      isChickletNone,
      onClearChicklets,
      emptyItems,
      lastInitialValue,
      hasInitialValues,
      events,
    } = this.props;
    return (
      <KdSelectEntity
        {...modelOptions}
        selectedValuesInitial={modelOptions.selectedValuesInitial}
        selectBehavior={selectBehavior}
        theme={theme}
        key={id}
        onItemAdded={onItemAdded}
        onItemRemoved={onItemRemoved}
        onOptionSelected={onOptionSelected}
        isChickletNone={isChickletNone}
        onClearChicklets={onClearChicklets}
        emptyItems={emptyItems}
        lastInitialValue={lastInitialValue}
        hasInitialValues={hasInitialValues}
        isEntityMultiple
        isEntityMultipleWithSelector={modelOptions.mainSelector.visible}
        events={events}
      />
    );
  }

  anySelected = () => this.state.selectedOption.id === ANY;

  render() {
    const { theme } = this.props;
    return (
      <div
        className={classNames(
          'o-layout',
          theme['o-layout'],
          { 'u-disabled': this.props.isDisabled },
          { [theme['u-disabled']]: this.props.isDisabled }
        )}
      >
        <div
          className={classNames(
            'o-layout__item',
            theme['o-layout__item'],
            { 'u-1/3': !this.anySelected() },
            { [theme['u-1/3']]: !this.anySelected() }
          )}
        >
          <BaseSelect
            theme={theme}
            options={this.options}
            onChange={this.onSelectChange}
            defaultValue={this.state.selectedOption.id}
          />
        </div>
        <div
          className={classNames(
            'o-layout__item',
            theme['o-layout__item'],
            { 'u-2/3 u-no-left-margin': !this.anySelected() },
            { [theme['u-2/3']]: !this.anySelected() },
            { [theme['u-no-left-margin']]: !this.anySelected() }
          )}
        >
          {this.optionHelper()}
        </div>
      </div>
    );
  }
}

KdSelectEntityMultiple.defaultProps = defaultProps;
KdSelectEntityMultiple.propTypes = propTypes;

export default wrap(KdSelectEntityMultiple);
