'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _defineProperty2 = require('babel-runtime/helpers/defineProperty');

var _defineProperty3 = _interopRequireDefault(_defineProperty2);

var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');

var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);

var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');

var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _createReactClass = require('create-react-class');

var _createReactClass2 = _interopRequireDefault(_createReactClass);

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

var _propTypes2 = _interopRequireDefault(_propTypes);

var _moment = require('moment');

var _moment2 = _interopRequireDefault(_moment);

var _classnames2 = require('classnames');

var _classnames3 = _interopRequireDefault(_classnames2);

var _CalendarPart = require('./range-calendar/CalendarPart');

var _CalendarPart2 = _interopRequireDefault(_CalendarPart);

var _TodayButton = require('./calendar/TodayButton');

var _TodayButton2 = _interopRequireDefault(_TodayButton);

var _OkButton = require('./calendar/OkButton');

var _OkButton2 = _interopRequireDefault(_OkButton);

var _TimePickerButton = require('./calendar/TimePickerButton');

var _TimePickerButton2 = _interopRequireDefault(_TimePickerButton);

var _CommonMixin = require('./mixin/CommonMixin');

var _CommonMixin2 = _interopRequireDefault(_CommonMixin);

var _util = require('./util/');

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

function noop() {}

function isEmptyArray(arr) {
  return Array.isArray(arr) && (arr.length === 0 || arr.every(function (i) {
    return !i;
  }));
}

function getValueFromSelectedValue(selectedValue) {
  var _selectedValue = (0, _slicedToArray3['default'])(selectedValue, 2),
      start = _selectedValue[0],
      end = _selectedValue[1];

  var newEnd = end && end.isSame(start, 'month') ? end.clone().add(1, 'month') : end;
  return [start, newEnd];
}

function normalizeAnchor(props, init) {
  var selectedValue = props.selectedValue || init && props.defaultSelectedValue;
  var value = props.value || init && props.defaultValue;
  var normalizedValue = value ? getValueFromSelectedValue(value) : getValueFromSelectedValue(selectedValue);
  return !isEmptyArray(normalizedValue) ? normalizedValue : init && [(0, _moment2['default'])(), (0, _moment2['default'])().add(1, 'months')];
}

function generateOptions(length) {
  var arr = [];
  for (var value = 0; value < length; value++) {
    arr.push(value);
  }
  return arr;
}

function onInputSelect(direction, value) {
  if (!value) {
    return;
  }
  var originalValue = this.state.selectedValue;
  var selectedValue = originalValue.concat();
  var index = direction === 'left' ? 0 : 1;
  selectedValue[index] = value;
  if (selectedValue[0] && this.compare(selectedValue[0], selectedValue[1]) > 0) {
    selectedValue[1 - index] = this.state.showTimePicker ? selectedValue[index] : undefined;
  }
  this.fireSelectValueChange(selectedValue);
}

var RangeCalendar = (0, _createReactClass2['default'])({
  propTypes: {
    prefixCls: _propTypes2['default'].string,
    dateInputPlaceholder: _propTypes2['default'].any,
    defaultValue: _propTypes2['default'].any,
    value: _propTypes2['default'].any,
    hoverValue: _propTypes2['default'].any,
    timePicker: _propTypes2['default'].any,
    showOk: _propTypes2['default'].bool,
    showToday: _propTypes2['default'].bool,
    defaultSelectedValue: _propTypes2['default'].array,
    selectedValue: _propTypes2['default'].array,
    onOk: _propTypes2['default'].func,
    showClear: _propTypes2['default'].bool,
    locale: _propTypes2['default'].object,
    onChange: _propTypes2['default'].func,
    onSelect: _propTypes2['default'].func,
    onValueChange: _propTypes2['default'].func,
    onHoverChange: _propTypes2['default'].func,
    format: _propTypes2['default'].oneOfType([_propTypes2['default'].object, _propTypes2['default'].string]),
    onClear: _propTypes2['default'].func,
    type: _propTypes2['default'].any,
    disabledDate: _propTypes2['default'].func,
    disabledTime: _propTypes2['default'].func
  },

  mixins: [_CommonMixin2['default']],

  getDefaultProps: function getDefaultProps() {
    return {
      type: 'both',
      defaultSelectedValue: [],
      onValueChange: noop,
      onHoverChange: noop,
      disabledTime: noop,
      showToday: true
    };
  },
  getInitialState: function getInitialState() {
    var props = this.props;
    var selectedValue = props.selectedValue || props.defaultSelectedValue;
    var value = normalizeAnchor(props, 1);
    return {
      selectedValue: selectedValue,
      prevSelectedValue: selectedValue,
      firstSelectedValue: null,
      hoverValue: props.hoverValue || [],
      value: value,
      showTimePicker: false,
      isStartMonthYearPanelShow: false,
      isEndMonthYearPanelShow: false
    };
  },
  componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
    var newState = {};
    if ('value' in nextProps) {
      if (nextProps.value) {
        newState.value = nextProps.value;
      } else {
        newState.value = normalizeAnchor(nextProps, 0);
      }
      this.setState(newState);
    }
    if ('hoverValue' in nextProps) {
      this.setState({ hoverValue: nextProps.hoverValue });
    }
    if ('selectedValue' in nextProps) {
      newState.selectedValue = nextProps.selectedValue;
      newState.prevSelectedValue = nextProps.selectedValue;
      this.setState(newState);
    }
  },
  onDatePanelEnter: function onDatePanelEnter() {
    if (this.hasSelectedValue()) {
      this.fireHoverValueChange(this.state.selectedValue.concat());
    }
  },
  onDatePanelLeave: function onDatePanelLeave() {
    if (this.hasSelectedValue()) {
      this.fireHoverValueChange([]);
    }
  },
  onSelect: function onSelect(value) {
    var type = this.props.type;
    var _state = this.state,
        selectedValue = _state.selectedValue,
        prevSelectedValue = _state.prevSelectedValue,
        firstSelectedValue = _state.firstSelectedValue;

    var nextSelectedValue = void 0;
    if (type === 'both') {
      if (!firstSelectedValue) {
        (0, _util.syncTime)(prevSelectedValue[0], value);
        nextSelectedValue = [value];
      } else if (this.compare(firstSelectedValue, value) < 0) {
        (0, _util.syncTime)(prevSelectedValue[1], value);
        nextSelectedValue = [firstSelectedValue, value];
      } else {
        (0, _util.syncTime)(prevSelectedValue[0], value);
        nextSelectedValue = [value, firstSelectedValue];
      }
    } else if (type === 'start') {
      (0, _util.syncTime)(prevSelectedValue[0], value);
      var endValue = selectedValue[1];
      nextSelectedValue = endValue && this.compare(endValue, value) > 0 ? [value, endValue] : [value];
    } else {
      // type === 'end'
      var startValue = selectedValue[0];
      if (startValue && this.compare(startValue, value) <= 0) {
        (0, _util.syncTime)(prevSelectedValue[1], value);
        nextSelectedValue = [startValue, value];
      } else {
        (0, _util.syncTime)(prevSelectedValue[0], value);
        nextSelectedValue = [value];
      }
    }

    this.fireSelectValueChange(nextSelectedValue);
  },
  onDayHover: function onDayHover(value) {
    var hoverValue = [];
    var _state2 = this.state,
        selectedValue = _state2.selectedValue,
        firstSelectedValue = _state2.firstSelectedValue;
    var type = this.props.type;

    if (type === 'start' && selectedValue[1]) {
      hoverValue = this.compare(value, selectedValue[1]) < 0 ? [value, selectedValue[1]] : [value];
    } else if (type === 'end' && selectedValue[0]) {
      hoverValue = this.compare(value, selectedValue[0]) > 0 ? [selectedValue[0], value] : [];
    } else {
      if (!firstSelectedValue) {
        return;
      }
      hoverValue = this.compare(value, firstSelectedValue) < 0 ? [value, firstSelectedValue] : [firstSelectedValue, value];
    }
    this.fireHoverValueChange(hoverValue);
  },
  onToday: function onToday() {
    var startValue = (0, _util.getTodayTime)(this.state.value[0]);
    var endValue = startValue.clone().add(1, 'months');
    this.setState({ value: [startValue, endValue] });
  },
  onOpenTimePicker: function onOpenTimePicker() {
    this.setState({
      showTimePicker: true
    });
  },
  onCloseTimePicker: function onCloseTimePicker() {
    this.setState({
      showTimePicker: false
    });
  },
  onOk: function onOk() {
    var selectedValue = this.state.selectedValue;

    if (this.isAllowedDateAndTime(selectedValue)) {
      this.props.onOk(this.state.selectedValue);
    }
  },
  onStartInputSelect: function onStartInputSelect() {
    for (var _len = arguments.length, oargs = Array(_len), _key = 0; _key < _len; _key++) {
      oargs[_key] = arguments[_key];
    }

    var args = ['left'].concat(oargs);
    return onInputSelect.apply(this, args);
  },
  onEndInputSelect: function onEndInputSelect() {
    for (var _len2 = arguments.length, oargs = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
      oargs[_key2] = arguments[_key2];
    }

    var args = ['right'].concat(oargs);
    return onInputSelect.apply(this, args);
  },
  onStartValueChange: function onStartValueChange(leftValue) {
    var value = [].concat((0, _toConsumableArray3['default'])(this.state.value));
    value[0] = leftValue;
    return this.fireValueChange(value);
  },
  onEndValueChange: function onEndValueChange(rightValue) {
    var value = [].concat((0, _toConsumableArray3['default'])(this.state.value));
    value[1] = rightValue;
    return this.fireValueChange(value);
  },
  onStartPanelChange: function onStartPanelChange(_ref) {
    var showMonthPanel = _ref.showMonthPanel,
        showYearPanel = _ref.showYearPanel;

    this.setState({ isStartMonthYearPanelShow: showMonthPanel || showYearPanel });
  },
  onEndPanelChange: function onEndPanelChange(_ref2) {
    var showMonthPanel = _ref2.showMonthPanel,
        showYearPanel = _ref2.showYearPanel;

    this.setState({ isEndMonthYearPanelShow: showMonthPanel || showYearPanel });
  },
  getStartValue: function getStartValue() {
    var value = this.state.value[0];
    var selectedValue = this.state.selectedValue;
    // keep selectedTime when select date
    if (selectedValue[0] && this.props.timePicker) {
      value = value.clone();
      (0, _util.syncTime)(selectedValue[0], value);
    }
    if (this.state.showTimePicker && selectedValue[0]) {
      return selectedValue[0];
    }
    return value;
  },
  getEndValue: function getEndValue() {
    var _state3 = this.state,
        value = _state3.value,
        selectedValue = _state3.selectedValue,
        showTimePicker = _state3.showTimePicker;

    var endValue = value[1] ? value[1].clone() : value[0].clone().add(1, 'month');
    // keep selectedTime when select date
    if (selectedValue[1] && this.props.timePicker) {
      (0, _util.syncTime)(selectedValue[1], endValue);
    }
    if (showTimePicker) {
      return selectedValue[1] ? selectedValue[1] : this.getStartValue();
    }
    return endValue;
  },

  // get disabled hours for second picker
  getEndDisableTime: function getEndDisableTime() {
    var _state4 = this.state,
        selectedValue = _state4.selectedValue,
        value = _state4.value;

    var startValue = selectedValue && selectedValue[0] || value[0].clone();
    // if startTime and endTime is same day..
    // the second time picker will not able to pick time before first time picker
    if (!selectedValue[1] || startValue.isSame(selectedValue[1], 'day')) {
      var hours = startValue.hour();
      var minutes = startValue.minute();
      var second = startValue.second();
      var _disabledHours = generateOptions(hours);
      var _disabledMinutes = generateOptions(minutes);
      var _disabledSeconds = generateOptions(second);
      return {
        disabledHours: function disabledHours() {
          return _disabledHours;
        },
        disabledMinutes: function disabledMinutes(hour) {
          if (hour === hours) {
            return _disabledMinutes;
          }
          return [];
        },
        disabledSeconds: function disabledSeconds(hour, minute) {
          if (hour === hours && minute === minutes) {
            return _disabledSeconds;
          }
          return [];
        }
      };
    }
    return null;
  },
  isAllowedDateAndTime: function isAllowedDateAndTime(selectedValue) {
    return (0, _util.isAllowedDate)(selectedValue[0], this.props.disabledDate, this.disabledStartTime) && (0, _util.isAllowedDate)(selectedValue[1], this.props.disabledDate, this.disabledEndTime);
  },
  hasSelectedValue: function hasSelectedValue() {
    var selectedValue = this.state.selectedValue;

    return !!selectedValue[1] && !!selectedValue[0];
  },
  compare: function compare(v1, v2) {
    if (this.props.timePicker) {
      return v1.diff(v2);
    }
    return v1.diff(v2, 'days');
  },
  fireSelectValueChange: function fireSelectValueChange(selectedValue, direct) {
    var timePicker = this.props.timePicker;
    var prevSelectedValue = this.state.prevSelectedValue;

    if (timePicker && timePicker.props.defaultValue) {
      var timePickerDefaultValue = timePicker.props.defaultValue;
      if (!prevSelectedValue[0] && selectedValue[0]) {
        (0, _util.syncTime)(timePickerDefaultValue[0], selectedValue[0]);
      }
      if (!prevSelectedValue[1] && selectedValue[1]) {
        (0, _util.syncTime)(timePickerDefaultValue[1], selectedValue[1]);
      }
    }

    if (!('selectedValue' in this.props)) {
      this.setState({
        selectedValue: selectedValue
      });
    }

    // 尚未选择过时间，直接输入的话
    if (!this.state.selectedValue[0] || !this.state.selectedValue[1]) {
      var startValue = selectedValue[0] || (0, _moment2['default'])();
      var endValue = selectedValue[1] || startValue.clone().add(1, 'months');
      this.setState({
        selectedValue: selectedValue,
        value: getValueFromSelectedValue([startValue, endValue])
      });
    }

    if (selectedValue[0] && !selectedValue[1]) {
      this.setState({ firstSelectedValue: selectedValue[0] });
      this.fireHoverValueChange(selectedValue.concat());
    }
    this.props.onChange(selectedValue);
    if (direct || selectedValue[0] && selectedValue[1]) {
      this.setState({
        prevSelectedValue: selectedValue,
        firstSelectedValue: null
      });
      this.fireHoverValueChange([]);
      this.props.onSelect(selectedValue);
    }
  },
  fireValueChange: function fireValueChange(value) {
    var props = this.props;
    if (!('value' in props)) {
      this.setState({
        value: value
      });
    }
    props.onValueChange(value);
  },
  fireHoverValueChange: function fireHoverValueChange(hoverValue) {
    var props = this.props;
    if (!('hoverValue' in props)) {
      this.setState({ hoverValue: hoverValue });
    }
    props.onHoverChange(hoverValue);
  },
  clear: function clear() {
    this.fireSelectValueChange([], true);
    this.props.onClear();
  },
  disabledStartTime: function disabledStartTime(time) {
    return this.props.disabledTime(time, 'start');
  },
  disabledEndTime: function disabledEndTime(time) {
    return this.props.disabledTime(time, 'end');
  },
  disabledStartMonth: function disabledStartMonth(month) {
    var value = this.state.value;

    return month.isSameOrAfter(value[1], 'month');
  },
  disabledEndMonth: function disabledEndMonth(month) {
    var value = this.state.value;

    return month.isSameOrBefore(value[0], 'month');
  },
  render: function render() {
    var _className, _classnames;

    var props = this.props;
    var state = this.state;
    var showTimePicker = state.showTimePicker,
        isStartMonthYearPanelShow = state.isStartMonthYearPanelShow,
        isEndMonthYearPanelShow = state.isEndMonthYearPanelShow;
    var prefixCls = props.prefixCls,
        dateInputPlaceholder = props.dateInputPlaceholder,
        timePicker = props.timePicker,
        showOk = props.showOk,
        locale = props.locale,
        showClear = props.showClear,
        showToday = props.showToday,
        type = props.type;
    var hoverValue = state.hoverValue,
        selectedValue = state.selectedValue;

    var className = (_className = {}, (0, _defineProperty3['default'])(_className, props.className, !!props.className), (0, _defineProperty3['default'])(_className, prefixCls, 1), (0, _defineProperty3['default'])(_className, prefixCls + '-hidden', !props.visible), (0, _defineProperty3['default'])(_className, prefixCls + '-range', 1), (0, _defineProperty3['default'])(_className, prefixCls + '-show-time-picker', showTimePicker), (0, _defineProperty3['default'])(_className, prefixCls + '-week-number', props.showWeekNumber), _className);
    var classes = (0, _classnames3['default'])(className);
    var newProps = {
      selectedValue: state.selectedValue,
      onSelect: this.onSelect,
      onDayHover: type === 'start' && selectedValue[1] || type === 'end' && selectedValue[0] || !!hoverValue.length ? this.onDayHover : undefined
    };

    var placeholder1 = void 0;
    var placeholder2 = void 0;

    if (dateInputPlaceholder) {
      if (Array.isArray(dateInputPlaceholder)) {
        var _dateInputPlaceholder = (0, _slicedToArray3['default'])(dateInputPlaceholder, 2);

        placeholder1 = _dateInputPlaceholder[0];
        placeholder2 = _dateInputPlaceholder[1];
      } else {
        placeholder1 = placeholder2 = dateInputPlaceholder;
      }
    }
    var showOkButton = showOk === true || showOk !== false && !!timePicker;
    var cls = (0, _classnames3['default'])((_classnames = {}, (0, _defineProperty3['default'])(_classnames, prefixCls + '-footer', true), (0, _defineProperty3['default'])(_classnames, prefixCls + '-range-bottom', true), (0, _defineProperty3['default'])(_classnames, prefixCls + '-footer-show-ok', showOkButton), _classnames));

    var startValue = this.getStartValue();
    var endValue = this.getEndValue();
    var todayTime = (0, _util.getTodayTime)(startValue);
    var thisMonth = todayTime.month();
    var thisYear = todayTime.year();
    var isTodayInView = startValue.year() === thisYear && startValue.month() === thisMonth || endValue.year() === thisYear && endValue.month() === thisMonth;
    var nextMonthOfStart = startValue.clone().add(1, 'months');
    var isClosestMonths = nextMonthOfStart.year() === endValue.year() && nextMonthOfStart.month() === endValue.month();
    return _react2['default'].createElement(
      'div',
      {
        ref: 'root',
        className: classes,
        style: props.style,
        tabIndex: '0'
      },
      props.renderSidebar(),
      _react2['default'].createElement(
        'div',
        { className: prefixCls + '-panel' },
        showClear && selectedValue[0] && selectedValue[1] ? _react2['default'].createElement('a', {
          className: prefixCls + '-clear-btn',
          role: 'button',
          title: locale.clear,
          onClick: this.clear
        }) : null,
        _react2['default'].createElement(
          'div',
          {
            className: prefixCls + '-date-panel',
            onMouseLeave: type !== 'both' ? this.onDatePanelLeave : undefined,
            onMouseEnter: type !== 'both' ? this.onDatePanelEnter : undefined
          },
          _react2['default'].createElement(_CalendarPart2['default'], (0, _extends3['default'])({}, props, newProps, {
            hoverValue: hoverValue,
            direction: 'left',
            disabledTime: this.disabledStartTime,
            disabledMonth: this.disabledStartMonth,
            format: this.getFormat(),
            value: startValue,
            placeholder: placeholder1,
            onInputSelect: this.onStartInputSelect,
            onValueChange: this.onStartValueChange,
            onPanelChange: this.onStartPanelChange,
            timePicker: timePicker,
            showTimePicker: showTimePicker,
            enablePrev: true,
            enableNext: !isClosestMonths || isEndMonthYearPanelShow
          })),
          _react2['default'].createElement(
            'span',
            { className: prefixCls + '-range-middle' },
            '~'
          ),
          _react2['default'].createElement(_CalendarPart2['default'], (0, _extends3['default'])({}, props, newProps, {
            hoverValue: hoverValue,
            direction: 'right',
            format: this.getFormat(),
            timePickerDisabledTime: this.getEndDisableTime(),
            placeholder: placeholder2,
            value: endValue,
            onInputSelect: this.onEndInputSelect,
            onValueChange: this.onEndValueChange,
            onPanelChange: this.onEndPanelChange,
            timePicker: timePicker,
            showTimePicker: showTimePicker,
            disabledTime: this.disabledEndTime,
            disabledMonth: this.disabledEndMonth,
            enablePrev: !isClosestMonths || isStartMonthYearPanelShow,
            enableNext: true
          }))
        ),
        _react2['default'].createElement(
          'div',
          { className: cls },
          props.renderFooter(),
          showToday || props.timePicker || showOkButton ? _react2['default'].createElement(
            'div',
            { className: prefixCls + '-footer-btn' },
            showToday ? _react2['default'].createElement(_TodayButton2['default'], (0, _extends3['default'])({}, props, {
              disabled: isTodayInView,
              value: state.value[0],
              onToday: this.onToday,
              text: locale.backToToday
            })) : null,
            props.timePicker ? _react2['default'].createElement(_TimePickerButton2['default'], (0, _extends3['default'])({}, props, {
              showTimePicker: showTimePicker,
              onOpenTimePicker: this.onOpenTimePicker,
              onCloseTimePicker: this.onCloseTimePicker,
              timePickerDisabled: !this.hasSelectedValue() || hoverValue.length
            })) : null,
            showOkButton ? _react2['default'].createElement(_OkButton2['default'], (0, _extends3['default'])({}, props, {
              onOk: this.onOk,
              okDisabled: !this.isAllowedDateAndTime(selectedValue) || !this.hasSelectedValue() || hoverValue.length
            })) : null
          ) : null
        )
      )
    );
  }
});

exports['default'] = RangeCalendar;
module.exports = exports['default'];