import classNames from 'classnames';
import extend from 'extend';
import isequal from 'lodash.isequal';
import React, { PropTypes } from 'react';

import BaseSelect from '../BaseSelect';
import options, { defaultOptions, buildCustomOption } from './options';
import wrap from '../ItemContainerWrapper';
import { KdSelectEntity } from '../KdSelectEntity';

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


const defaultProps = {
  selectedValuesInitial: [],
  selectBehavior: ADD_CHICKLET,
  isDisabled: false,
  mainSelector: {
    visible: true,
    selected: '',
    optionValues: {
      anyOption: {
        visible: true,
      },
      customOptions: [],
      userSpecifiedOption: {
        visible: true,
      },
    },
  },
  events: {},
  autoComplete: {
    clearTextboxOnSelection: true,
    renderClearTextboxButton: true,
  },
  multipleCategories: true,
};

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

  api: PropTypes.shape({
    url: PropTypes.string.isRequired,
    key: PropTypes.string.isRequired,
  }),

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

  mainSelector: PropTypes.shape({
    visible: PropTypes.bool,
    selected: PropTypes.string,

    optionValues: PropTypes.shape({
      selectOption: PropTypes.shape({
        visible: PropTypes.bool,
        label: PropTypes.string,
      }),
      anyOption: PropTypes.shape({
        visible: PropTypes.bool,
        label: PropTypes.string,
      }),
      customOptions: PropTypes.arrayOf(
        PropTypes.shape({
          label: PropTypes.string,
          modelOptions: PropTypes.shape({
            kdFilterModel: PropTypes.object.isRequired,

            mainSelector: PropTypes.shape({
              visible: PropTypes.bool,
              selected: PropTypes.string,

              optionValues: PropTypes.shape({
                selectOption: PropTypes.shape({
                  visible: PropTypes.bool,
                  label: PropTypes.string,
                }),
                anyOption: PropTypes.shape({
                  visible: PropTypes.bool,
                  label: PropTypes.string,
                }),
                customOptions: PropTypes.array,
                userSpecifiedOption: PropTypes.shape({
                  visible: PropTypes.bool,
                  label: PropTypes.string,
                }),
              }),
            }),

            autoComplete: PropTypes.shape({
              onSuccess: PropTypes.func,
              onRender: PropTypes.func,
              onSelect: PropTypes.func,
              onFail: PropTypes.func,
              onDone: PropTypes.func,
              placeholderText: PropTypes.string,
              clearTextboxOnSelection: PropTypes.bool,
              renderClearTextboxButton: PropTypes.bool,
            }),

            events: PropTypes.shape({
              onSelect: PropTypes.func,
              onChange: PropTypes.func,
            }),
          }),
        }),
      ),
      userSpecifiedOption: PropTypes.shape({
        visible: PropTypes.bool,
        label: PropTypes.string,
      }),
    }),
  }),

  autoComplete: PropTypes.shape({
    onSuccess: PropTypes.func,
    onRender: PropTypes.func,
    onSelect: PropTypes.func,
    onFail: PropTypes.func,
    onDone: PropTypes.func,
    placeholderText: PropTypes.string,
    clearTextboxOnSelection: PropTypes.bool,
    renderClearTextboxButton: PropTypes.bool,
  }),

  selectedValuesInitial: PropTypes.array,

};

class KdSelectEntityMultiple extends React.Component {

  constructor(props) {
    super(props);

    this.mainSelector = extend(true, {}, defaultProps.mainSelector, this.props.mainSelector);
    this.options = this.propBasedOptions();

    this.state = {
      selectedOption: this.options[0],
      selectedValue: '',
    };
  }

  componentWillReceiveProps(nextProps) {
    const newCustomOptions = nextProps.mainSelector.optionValues.customOptions;
    const customOptions = this.mainSelector.optionValues.customOptions;
    if (!isequal(newCustomOptions, customOptions)) {
      this.mainSelector = extend(true, {}, defaultProps.mainSelector, nextProps.mainSelector);
      this.options = this.propBasedOptions();
      this.setState({
        selectedOption: this.options[0],
        selectedValue: '',
      });
    }
  }

  propBasedOptions() {
    const { anyOption, customOptions } = this.mainSelector.optionValues;
    let initialOptions = [...defaultOptions];

    if (anyOption.visible && anyOption.label) {
      options.optionsMap[ANY].displayName = anyOption.label;
    } else {
      initialOptions = initialOptions.filter(key => key !== ANY);
    }

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

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

    if (selectedOption.id === ANY) {
      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,
      api,
      onItemAdded,
      onItemRemoved,
      onOptionSelected,
      isChickletNone,
      onClearChicklets,
      emptyItems,
      lastInitialValue,
      hasInitialValues,
      events,
    } = this.props;
    return (
      <KdSelectEntity
        {...modelOptions}
        selectedValuesInitial={modelOptions.selectedValuesInitial}
        theme={theme}
        key={id}
        api={api}
        onItemAdded={onItemAdded}
        onItemRemoved={onItemRemoved}
        onOptionSelected={onOptionSelected}
        isChickletNone={isChickletNone}
        onClearChicklets={onClearChicklets}
        emptyItems={emptyItems}
        lastInitialValue={lastInitialValue}
        hasInitialValues={hasInitialValues}
        isEntityMultiple
        isEntityMultipleWithSelector={modelOptions.mainSelector.visible}
        events={events}
      />
    );
  }

  anySelected = () => {
    return 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);
