'use strict';

exports.__esModule = true;

var _isFunction2 = require('lodash/isFunction');

var _isFunction3 = _interopRequireDefault(_isFunction2);

var _debounce2 = require('lodash/debounce');

var _debounce3 = _interopRequireDefault(_debounce2);

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _react = require('react');

var React = _interopRequireWildcard(_react);

var _reactDom = require('react-dom');

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _domLib = require('dom-lib');

var _utils = require('./utils');

var _Tooltip = require('./Tooltip');

var _Tooltip2 = _interopRequireDefault(_Tooltip);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); } /* eslint-disable react/no-find-dom-node */


var Slider = function (_React$Component) {
  _inherits(Slider, _React$Component);

  function Slider(props) {
    _classCallCheck(this, Slider);

    var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));

    _this.onWindowResizeListener = null;

    _this.hanldeClick = function (event) {
      if (_this.props.disabled) {
        return;
      }

      var _this$props = _this.props,
          vertical = _this$props.vertical,
          min = _this$props.min;

      var barOffset = (0, _domLib.getOffset)(_this.bar);
      var offset = vertical ? event.pageY - barOffset.top : event.pageX - barOffset.left;
      _this.setValue(_this.calculateValue(offset) + min);
    };

    _this.mouseMoveTracker = null;
    _this.bar = null;
    _this.handle = null;

    _this.hanldeMouseDown = function (event) {
      if (_this.props.disabled) {
        return;
      }
      _this.mouseMoveTracker = _this.getMouseMoveTracker();
      _this.mouseMoveTracker.captureMouseMoves(event);
      _this.setState({
        handleDown: true
      });
    };

    _this.hanldeDragEnd = function () {
      _this.releaseMouseMoves();
      _this.setState({
        handleDown: false
      });
    };

    _this.hanldeDragMove = function (deltaX, deltaY, event) {
      if (!_this.mouseMoveTracker || !_this.mouseMoveTracker.isDragging()) {
        return;
      }

      var _this$props2 = _this.props,
          vertical = _this$props2.vertical,
          min = _this$props2.min;

      var barOffset = (0, _domLib.getOffset)(_this.bar);
      var offset = vertical ? event.pageY - barOffset.top : event.pageX - barOffset.left;

      _this.setValue(_this.calculateValue(offset) + min);
      _this.setTooltipPosition();
    };

    _this.releaseMouseMoves = function () {
      if (_this.mouseMoveTracker) {
        _this.mouseMoveTracker.releaseMouseMoves();
        _this.mouseMoveTracker = null;
      }
    };

    _this.handleWindowResize = function () {
      _this.updateBar();
    };

    _this.addPrefix = function (name) {
      return (0, _utils.prefix)(_this.props.classPrefix)(name);
    };

    _this.handleRef = function (ref) {
      _this.handle = ref;
    };

    _this.barRef = function (ref) {
      _this.bar = ref;
    };

    _this.state = {
      value: _this.checkValue(props.defaultValue, props),
      barWidth: 0,
      barHeight: 0
    };
    return _this;
  }

  Slider.prototype.componentDidMount = function componentDidMount() {
    this.updateBar();
    this.onWindowResizeListener = (0, _domLib.on)(window, 'resize', (0, _debounce3.default)(this.handleWindowResize, 100));
  };

  Slider.prototype.componentWillUnmount = function componentWillUnmount() {
    this.releaseMouseMoves();
    this.onWindowResizeListener && this.onWindowResizeListener.off();
  };

  Slider.prototype.getMouseMoveTracker = function getMouseMoveTracker() {
    return this.mouseMoveTracker || new _domLib.DOMMouseMoveTracker(this.hanldeDragMove, this.hanldeDragEnd, document.body);
  };

  Slider.prototype.getSplitCount = function getSplitCount() {
    var _props = this.props,
        min = _props.min,
        step = _props.step;

    var max = this.getMax();
    return (max - min) / step;
  };

  Slider.prototype.getMax = function getMax(props) {
    var _ref = props || this.props,
        max = _ref.max,
        min = _ref.min,
        step = _ref.step;

    return Math.floor((max - min) / step) * step + min;
  };

  Slider.prototype.getValue = function getValue() {
    var value = this.props.value;

    return typeof value === 'undefined' ? this.state.value : this.checkValue(value);
  };

  Slider.prototype.setValue = function setValue(value) {
    var _props2 = this.props,
        onChange = _props2.onChange,
        min = _props2.min;

    var max = this.getMax();
    if (value < min) {
      value = min;
    }
    if (value > max) {
      value = max;
    }

    this.setState({ value: value });
    onChange && onChange(value);
  };

  Slider.prototype.setTooltipPosition = function setTooltipPosition() {
    var tooltip = this.props.tooltip;

    if (tooltip) {
      var handle = (0, _reactDom.findDOMNode)(this.handle);
      var tip = handle.querySelector('.' + this.addPrefix('tooltip'));
      var width = (0, _domLib.getWidth)(tip);
      (0, _domLib.addStyle)(tip, 'left', '-' + width / 2 + 'px');
    }
  };

  Slider.prototype.checkValue = function checkValue(value, props) {
    var _ref2 = props || this.props,
        min = _ref2.min;

    var max = this.getMax(props);
    if (value < min) {
      return min;
    }
    if (value > max) {
      return max;
    }
    return value;
  };

  /**
   * 通过偏移量计算值
   * @param {number} offset 偏移量
   */


  Slider.prototype.calculateValue = function calculateValue(offset) {
    var _props3 = this.props,
        step = _props3.step,
        vertical = _props3.vertical;
    var _state = this.state,
        barWidth = _state.barWidth,
        barHeight = _state.barHeight;

    var count = this.getSplitCount();

    var value = 0;

    if (isNaN(offset)) {
      return value;
    }

    if (vertical) {
      value = Math.round(offset / (barHeight / count)) * step;
    } else {
      value = Math.round(offset / (barWidth / count)) * step;
    }

    return value;
  };

  /**
   * 释放鼠标移动事件
   */


  Slider.prototype.updateBar = function updateBar() {
    this.setState({
      barWidth: (0, _domLib.getWidth)(this.bar),
      barHeight: (0, _domLib.getHeight)(this.bar)
    });
  };

  Slider.prototype.renderMark = function renderMark(mark, last) {
    var _classNames;

    var renderMark = this.props.renderMark;

    var classes = (0, _classnames2.default)(this.addPrefix('mark'), (_classNames = {}, _classNames[this.addPrefix('last-mark')] = last, _classNames));

    if (renderMark) {
      return React.createElement(
        'span',
        { className: classes },
        React.createElement(
          'span',
          { className: this.addPrefix('mark-content') },
          renderMark(mark)
        )
      );
    }

    return null;
  };

  /**
   * 渲染标尺
   */


  Slider.prototype.renderGraduated = function renderGraduated() {
    var _props4 = this.props,
        vertical = _props4.vertical,
        step = _props4.step,
        min = _props4.min;

    var max = this.getMax();
    var count = this.getSplitCount();
    var barHeight = this.state.barHeight;

    var value = this.getValue();
    var graduatedItems = [];
    var pass = value / step - min / step;
    var active = Math.ceil((value - min) / (max - min) * count);

    for (var i = 0; i < count; i += 1) {
      var _classNames2;

      var style = {};
      var classes = (0, _classnames2.default)((_classNames2 = {}, _classNames2[this.addPrefix('pass')] = i <= pass, _classNames2[this.addPrefix('active')] = i === active, _classNames2));

      if (barHeight && vertical) {
        style.height = barHeight / count;
      }
      var _mark = i * step + min;
      var last = i === count - 1;

      graduatedItems.push(React.createElement(
        'li',
        { className: classes, style: style, key: i },
        this.renderMark(_mark),
        last && this.renderMark(max, true)
      ));
    }

    return React.createElement(
      'div',
      { className: this.addPrefix('graduator') },
      React.createElement(
        'ul',
        null,
        graduatedItems
      )
    );
  };

  Slider.prototype.renderHanlde = function renderHanlde() {
    var _extends2, _classNames3;

    var _props5 = this.props,
        handleClassName = _props5.handleClassName,
        handleTitle = _props5.handleTitle,
        min = _props5.min,
        vertical = _props5.vertical,
        tooltip = _props5.tooltip,
        hanldeStyle = _props5.hanldeStyle;

    var max = this.getMax();
    var handleDown = this.state.handleDown;

    var value = this.getValue();

    var direction = vertical ? 'top' : 'left';
    var style = _extends({}, hanldeStyle, (_extends2 = {}, _extends2[direction] = (value - min) / (max - min) * 100 + '%', _extends2));
    var handleClasses = (0, _classnames2.default)(this.addPrefix('handle'), handleClassName, (_classNames3 = {}, _classNames3[this.addPrefix('showtip')] = handleDown, _classNames3));

    return React.createElement(
      'div',
      {
        className: handleClasses,
        role: 'presentation',
        onMouseDown: this.hanldeMouseDown,
        style: style,
        ref: this.handleRef
      },
      tooltip && React.createElement(
        _Tooltip2.default,
        { placement: 'top', className: this.addPrefix('tooltip') },
        value
      ),
      handleTitle
    );
  };

  Slider.prototype.renderProgress = function renderProgress() {
    var _style;

    var _props6 = this.props,
        vertical = _props6.vertical,
        min = _props6.min;

    var max = this.getMax();
    var value = this.getValue();
    var key = vertical ? 'height' : 'width';
    var style = (_style = {}, _style[key] = (value - min) / (max - min) * 100 + '%', _style);

    return React.createElement('div', { style: style, className: this.addPrefix('progress-bar') });
  };

  Slider.prototype.render = function render() {
    var _classNames4;

    var _props7 = this.props,
        graduated = _props7.graduated,
        className = _props7.className,
        barClassName = _props7.barClassName,
        progress = _props7.progress,
        vertical = _props7.vertical,
        disabled = _props7.disabled,
        classPrefix = _props7.classPrefix,
        renderMark = _props7.renderMark,
        rest = _objectWithoutProperties(_props7, ['graduated', 'className', 'barClassName', 'progress', 'vertical', 'disabled', 'classPrefix', 'renderMark']);

    var handleDown = this.state.handleDown;

    var classes = (0, _classnames2.default)(classPrefix, className, (_classNames4 = {}, _classNames4[this.addPrefix('vertical')] = vertical, _classNames4[this.addPrefix('disabled')] = disabled, _classNames4[this.addPrefix('graduated')] = graduated, _classNames4[this.addPrefix('dragging')] = handleDown, _classNames4[this.addPrefix('with-mark')] = (0, _isFunction3.default)(renderMark), _classNames4));

    var unhandled = (0, _utils.getUnhandledProps)(Slider, rest);

    return React.createElement(
      'div',
      _extends({}, unhandled, { className: classes, onClick: this.hanldeClick, role: 'presentation' }),
      React.createElement(
        'div',
        { className: (0, _classnames2.default)(this.addPrefix('bar'), barClassName), ref: this.barRef },
        progress && this.renderProgress(),
        graduated && this.renderGraduated()
      ),
      this.renderHanlde()
    );
  };

  return Slider;
}(React.Component);

Slider.defaultProps = {
  min: 0,
  max: 100,
  step: 1,
  defaultValue: 0,
  tooltip: true
};
Slider.handledProps = ['barClassName', 'className', 'classPrefix', 'defaultValue', 'disabled', 'graduated', 'handleClassName', 'handleTitle', 'hanldeStyle', 'max', 'min', 'onChange', 'progress', 'renderMark', 'step', 'tooltip', 'value', 'vertical'];
Slider.propTypes = {
  min: _propTypes2.default.number.isRequired,
  max: _propTypes2.default.number.isRequired,
  step: _propTypes2.default.number.isRequired,
  value: _propTypes2.default.number,
  defaultValue: _propTypes2.default.number.isRequired,
  className: _propTypes2.default.string,
  classPrefix: _propTypes2.default.string,
  handleClassName: _propTypes2.default.string,
  handleTitle: _propTypes2.default.node,
  barClassName: _propTypes2.default.string,
  hanldeStyle: _propTypes2.default.object,
  disabled: _propTypes2.default.bool,
  graduated: _propTypes2.default.bool,
  tooltip: _propTypes2.default.bool,
  progress: _propTypes2.default.bool,
  vertical: _propTypes2.default.bool,
  onChange: _propTypes2.default.func,
  renderMark: _propTypes2.default.func
};
exports.default = (0, _utils.defaultProps)({
  classPrefix: 'slider'
})(Slider);