import React, { PropTypes } from 'react';
import classNames from 'classnames';

import options, { defaultOptions, isValidOption, buildCustomOption } from './options';
import KdSlider from '../KdSlider';
import BaseSelect from '../BaseSelect';
import wrap from '../ItemContainerWrapper';
import { ANY } from '../../constants';

const optionRegex = /^mainSelectorOptions(.+)IsVisible$/;
const propTypes = {
  isDisabled: PropTypes.bool,
  onOptionSelected: PropTypes.func,
  onItemAdded: PropTypes.func,
  onClearChicklets: PropTypes.func,
  selectedValuesInitial: PropTypes.array,
  values: PropTypes.array,
  min: PropTypes.number,
  max: PropTypes.number,

  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,
      }),
    }),
  }),

  events: PropTypes.shape({
    onSelect: PropTypes.func,
    onChange: PropTypes.func,
  }),
};
const defaultProps = {
  isDisabled: false,
  selectedValuesInitial: [],
  mainSelector: {
    visible: false,
    selected: '',
    optionValues: {
      anyOption: {
        visible: true,
      },
      customOptions: [],
      userSpecifiedOption: {
        visible: false,
      },
    },
  },
  events: {},
};

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

    this.options = this.propBasedOptions();

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

    this.onSelectChange = this.onSelectChange.bind(this);
    this.onSelectedValueChange = this.onSelectedValueChange.bind(this);
  }

  componentWillMount() {
    this.props.onOptionSelected(this.state.selectedOption.id);

    this.props.selectedValuesInitial.forEach(({ operator, value }) => {
      const relatedOption = this.options.find(option => option.key === operator);

      if (relatedOption) {
        relatedOption.selected = value;
        this.props.onItemAdded(relatedOption.selected);
      }
    });
  }

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

    if (selectedOption.loadDefaultValue()) {
      this.props.onItemAdded(selectedOption.selected);
    }

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

      if (this.props.events.onSelect) {
        const value = selectedOption.selected ? selectedOption.selected.value : null;
        this.props.events.onSelect(
          {
            data: {
              label: selectedOption.id,
              value,
            },
          },
        );
      }

      if (selectedOption.key === ANY) {
        this.props.onClearChicklets();
      }
    });
  }

  onSelectedValueChange(newValue) {
    const { selectedOption } = this.state;
    selectedOption.selected = newValue;

    this.props.onItemAdded(selectedOption.selected);

    this.setState({ selectedValue: selectedOption.selectedLabel }, () => {
      if (this.props.events.onChange) {
        const value = selectedOption.selected ? selectedOption.selected.value : null;
        this.props.events.onChange(
          {
            data: {
              label: selectedOption.id,
              value,
            },
          },
        );
      }
    });
  }

  propBasedOptions() {
    if (!this.props.mainSelector.visible) {
      return [options.create('SpecifyARange')];
    }

    const optionSet = new Set(defaultOptions);

    Object.keys(this.props).forEach((key) => {
      if (Object.prototype.hasOwnProperty.call(this.props, key) && key.match(optionRegex)) {
        const optionEnabled = this.props[key];
        const optionKey = key.match(optionRegex)[1];

        if (optionEnabled) {
          if (isValidOption(optionKey)) {
            optionSet.add(optionKey);
          } else {
            optionSet.delete(optionKey);
          }
        }
      }
    });

    return Array.from(optionSet)
      .map(type => options.create(type))
      .concat(this.props.mainSelector.optionValues.customOptions.map(buildCustomOption));
  }

  optionHelper() {
    switch (this.state.selectedOption.id) {
      case 'range': {
        const { min, max, values } = this.props;
        let selectedValues;
        if (this.state.selectedOption.selected) {
          selectedValues = this.state.selectedOption.selectedValue;
        } else {
          selectedValues = values;
        }
        return (
          <KdSlider
            min={min}
            max={max}
            values={selectedValues}
            onSelectedValue={this.onSelectedValueChange}
          />
        );
      }
      case 'eq':
      case 'gteq':
      case 'lteq':
        return (
          <input
            className={'c-kd-select-number__input u-1/1'}
            onChange={this.onSelectedValueChange}
            value={this.state.selectedValue || ''}
            type={'text'}
          />
        );
      default:
        return null;
    }
  }

  render() {
    return (
      <div className={classNames({ 'u-disabled': this.props.isDisabled })}>
        {this.props.mainSelector.visible &&
          <BaseSelect options={this.options} onChange={this.onSelectChange} />}
        {this.optionHelper()}
      </div>
    );
  }
}

KdSelectNumber.propTypes = propTypes;
KdSelectNumber.defaultProps = defaultProps;

export default wrap(KdSelectNumber);
