import classNames from 'classnames';
import uniq from 'lodash.uniq';
import flatten from 'lodash.flatten';
import React, { PropTypes } from 'react';

import wrap from '../ItemContainerWrapper';
import MainButton from './MainButton';
import OptionsList from './OptionsList';

const defaultProps = {
};

const propTypes = {
  theme: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.func,
  ]).isRequired,
  placeholderText: PropTypes.string,
  placeholderHandler: PropTypes.func,
  dropDownOptions: PropTypes.arrayOf(
    PropTypes.shape({
      label: PropTypes.string,
      options: PropTypes.arrayOf(
        PropTypes.shape({
          value: PropTypes.string,
          label: PropTypes.string,
        }),
      ),
    }),
  ),
};

class KdSelectStringGroup extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      selecteds: [],
      optionsListVisible: false,
      mainButtonLabel: props.placeHolderText,
    };

    this.changeOption = this.changeOption.bind(this);
    this.changeGroup = this.changeGroup.bind(this);
    this.checkAll = this.checkAll.bind(this);
    this.uncheckAll = this.uncheckAll.bind(this);
    this.toggleOptionsList = this.toggleOptionsList.bind(this);
    this.mainButtonLabel = this.mainButtonLabel.bind(this);
    this.renderOptionsList = this.renderOptionsList.bind(this);
  }

  changeOption(option, checked) {
    const { selecteds } = this.state;
    let newSelecteds;

    if (checked) {
      newSelecteds = [...selecteds, option];
    } else {
      newSelecteds = selecteds.filter(selectedOption => selectedOption !== option);
    }

    this.setState(Object.assign({}, this.state, { selecteds: newSelecteds }));
  }

  changeGroup(group, checked) {
    let newSelecteds;

    if (checked) {
      newSelecteds = [...this.state.selecteds, ...group.options];
    } else {
      newSelecteds = this.state.selecteds.filter(selected => !group.options.includes(selected));
    }

    this.setState(Object.assign({}, this.state, { selecteds: uniq(newSelecteds) }));
  }

  checkAll() {
    const allOptions = flatten(this.props.dropDownOptions.map(group => group.options));
    this.setState(Object.assign({}, this.state, { selecteds: allOptions }));
  }

  uncheckAll() {
    this.setState(Object.assign({}, this.state, { selecteds: [] }));
  }

  toggleOptionsList() {
    this.setState(
      Object.assign({}, this.state, { optionsListVisible: !this.state.optionsListVisible }),
    );
  }

  mainButtonLabel() {
    const { selecteds } = this.state;

    if (selecteds.length === 0) {
      return this.props.placeholderText || 'Search...';
    }

    if (this.props.placeholderHandler) {
      return this.props.placeholderHandler(selecteds);
    }

    return `${selecteds.length} Selected`;
  }

  renderOptionsList() {
    if (this.state.optionsListVisible) {
      return (
        <OptionsList
          theme={this.props.theme}
          checkAll={this.checkAll}
          uncheckAll={this.uncheckAll}
          dropDownOptions={this.props.dropDownOptions}
          changeOption={this.changeOption}
          changeGroup={this.changeGroup}
          toggleOptionsList={this.toggleOptionsList}
          selecteds={this.state.selecteds}
        />
      );
    }

    return null;
  }

  render() {
    const { theme } = this.props;

    return (
      <div className={classNames('c-kd-select-string-group', theme['c-kd-select-string-group'])}>
        <MainButton
          theme={theme}
          label={this.mainButtonLabel()}
          active={this.state.optionsListVisible}
          onClick={this.toggleOptionsList}
        />
        {this.renderOptionsList()}
      </div>
    );
  }
}

KdSelectStringGroup.propTypes = propTypes;
KdSelectStringGroup.defaultProps = defaultProps;

export default wrap(KdSelectStringGroup);
