import classNames from 'classnames';
import clamp from 'lodash.clamp';
import React, { PropTypes } from 'react';
import Slider from 'rc-slider';

import { numberHasErrors, isNumber } from '../../utils/validations.js';
import { buildOptionLabel } from '../KdSelectNumber/options';

const Input = ({ value, onChange, name, theme }) => {
  return (
    <input
      className={
        classNames(
          'c-kd-slider__input',
          'c-kd__input',
          theme['c-kd-slider__input'],
          theme['c-kd__input'],
        )
      }
      name={name}
      type="text"
      value={value}
      onChange={onChange}
    />
  );
};

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

    this.prepareSlider();
  }

  componentDidMount() {
    this.props.onSelectedValue(this.state.sliderValues);
  }

  prepareSlider = () => {
    const { min, max, values, onSelectedValue } = this.props;

    const start = values[0] || min;
    const end = values[1] || max;
    const sliderValues = [start, end];

    this.state = { start, end, sliderValues };
  }

  onSliderChange = (sliderValues) => {
    this.props.onSelectedValue(sliderValues);
    this.setState({ start: sliderValues[0], end: sliderValues[1], sliderValues });
  }

  onInputChange = ({ target }) => {
    const { value, name } = target;
    const { min, max, onSelectedValue, onError, isChickletNone, onChange } = this.props;
    const { start, end } = this.state;
    let valueToCheck = value;

    if (name === 'start') {
      valueToCheck = [value, end];
    } else if (name === 'end') {
      valueToCheck = [start, value];
    }
    const errors = numberHasErrors(valueToCheck, min, max);
    if (errors) {
      onError({ errors });
      this.setState({ [name]: value },
        () => (
          onChange({ data: { value: this.state.sliderValues } })
        )
      );
    } else {
      const nextState = Object.assign({}, this.state, { [name]: value });
      const sliderValues = this.safetyValues(nextState);

      onSelectedValue(sliderValues);
      this.setState({ [name]: value, sliderValues });
    }
  }

  safetyValues({ start, end, sliderValues }) {
    let newValues = sliderValues;
    let newStart = this.clampSliderValue(start);
    const newEnd = this.clampSliderValue(end);

    if (newStart > newEnd) {
      newStart = newEnd;
    }

    if (isNumber(newStart)) {
      newValues[0] = newStart;
    }

    if (isNumber(newEnd)) {
      newValues[1] = newEnd;
    }

    return newValues;
  }

  clampSliderValue = (value) => {
    return clamp(value, this.props.min, this.props.max);
  }

  renderLabel = () => {
    const { slider: { label: { visible, handler } }, theme } = this.props;
    if (!visible) {
      return null;
    }

    const label = buildOptionLabel({
      value: this.state.sliderValues,
      operator: 'Between',
      handler,
      unit: this.props.unit,
    });
    return (
      <span className={classNames('c-kd-slider__label', theme['c-kd-slider__label'])}>
        {label}
      </span>
    );
  }

  render() {
    const { start, sliderValues, end } = this.state;
    const { theme } = this.props;
    return (
      <div className={classNames('c-kd-select-number__slider', theme['c-kd-select-number__slider'])}>
        {this.renderLabel()}
        <Input
          theme={theme}
          value={start}
          onChange={this.onInputChange}
          name="start"
        />
        <Slider
          range
          allowCross={false}
          onChange={this.onSliderChange}
          value={sliderValues}
          min={this.props.min}
          max={this.props.max}
        />
        <Input
          theme={theme}
          value={end}
          onChange={this.onInputChange}
          name={'end'}
        />
      </div>
    );
  }
}

KdSlider.defaultProps = {
  min: 0,
  max: 100,
  values: [],
};

KdSlider.propTypes = {
  theme: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.func,
  ]).isRequired,
  unit: PropTypes.string,
  min: PropTypes.number,
  max: PropTypes.number,
  onSelectedValue: PropTypes.func,
  onError: PropTypes.func,
  slider: PropTypes.shape({
    label: PropTypes.shape({
      visible: PropTypes.bool,
      handler: PropTypes.func,
    }),
  }),
};

export default KdSlider;
