import * as _vue from "vue";
import PropTypes from '../../_util/vue-types';
import classNames from '../../_util/classNames';
import KeyCode from '../../_util/KeyCode';
import { initDefaultProps, hasProp, getOptionProps, getComponent, findDOMNode } from '../../_util/props-util';
import BaseMixin from '../../_util/BaseMixin';
import { getOffsetLeft } from './util';
import Star from './Star';
var rateProps = {
  disabled: PropTypes.bool,
  value: PropTypes.number,
  defaultValue: PropTypes.number,
  count: PropTypes.number,
  allowHalf: PropTypes.bool,
  allowClear: PropTypes.bool,
  prefixCls: PropTypes.string,
  character: PropTypes.any,
  characterRender: PropTypes.func,
  tabindex: PropTypes.number,
  autofocus: PropTypes.bool
};

function noop() {}

export default {
  name: 'Rate',
  mixins: [BaseMixin],
  inheritAttrs: false,
  props: initDefaultProps(rateProps, {
    defaultValue: 0,
    count: 5,
    allowHalf: false,
    allowClear: true,
    prefixCls: 'rc-rate',
    tabindex: 0,
    character: '★'
  }),
  data: function data() {
    var value = this.value;

    if (!hasProp(this, 'value')) {
      value = this.defaultValue;
    }

    return {
      sValue: value,
      focused: false,
      cleanedValue: null,
      hoverValue: undefined
    };
  },
  watch: {
    value: function value(val) {
      this.setState({
        sValue: val
      });
    }
  },
  mounted: function mounted() {
    var _this = this;

    this.$nextTick(function () {
      if (_this.autofocus && !_this.disabled) {
        _this.focus();
      }
    });
  },
  methods: {
    onHover: function onHover(event, index) {
      var hoverValue = this.getStarValue(index, event.pageX);
      var cleanedValue = this.cleanedValue;

      if (hoverValue !== cleanedValue) {
        this.setState({
          hoverValue: hoverValue,
          cleanedValue: null
        });
      }

      this.__emit('hoverChange', hoverValue);
    },
    onMouseLeave: function onMouseLeave() {
      this.setState({
        hoverValue: undefined,
        cleanedValue: null
      });

      this.__emit('hoverChange', undefined);
    },
    onClick: function onClick(event, index) {
      var allowClear = this.allowClear,
          value = this.sValue;
      var newValue = this.getStarValue(index, event.pageX);
      var isReset = false;

      if (allowClear) {
        isReset = newValue === value;
      }

      this.onMouseLeave(true);
      this.changeValue(isReset ? 0 : newValue);
      this.setState({
        cleanedValue: isReset ? newValue : null
      });
    },
    onFocus: function onFocus() {
      this.setState({
        focused: true
      });

      this.__emit('focus');
    },
    onBlur: function onBlur() {
      this.setState({
        focused: false
      });

      this.__emit('blur');
    },
    onKeyDown: function onKeyDown(event) {
      var keyCode = event.keyCode;
      var count = this.count,
          allowHalf = this.allowHalf;
      var sValue = this.sValue;

      if (keyCode === KeyCode.RIGHT && sValue < count) {
        if (allowHalf) {
          sValue += 0.5;
        } else {
          sValue += 1;
        }

        this.changeValue(sValue);
        event.preventDefault();
      } else if (keyCode === KeyCode.LEFT && sValue > 0) {
        if (allowHalf) {
          sValue -= 0.5;
        } else {
          sValue -= 1;
        }

        this.changeValue(sValue);
        event.preventDefault();
      }

      this.__emit('keydown', event);
    },
    getStarDOM: function getStarDOM(index) {
      return findDOMNode(this.$refs['stars' + index]);
    },
    getStarValue: function getStarValue(index, x) {
      var value = index + 1;

      if (this.allowHalf) {
        var starEle = this.getStarDOM(index);
        var leftDis = getOffsetLeft(starEle);
        var width = starEle.clientWidth;

        if (x - leftDis < width / 2) {
          value -= 0.5;
        }
      }

      return value;
    },
    focus: function focus() {
      if (!this.disabled) {
        this.$refs.rateRef.focus();
      }
    },
    blur: function blur() {
      if (!this.disabled) {
        this.$refs.rateRef.blur();
      }
    },
    changeValue: function changeValue(value) {
      if (!hasProp(this, 'value')) {
        this.setState({
          sValue: value
        });
      }

      this.__emit('update:value', value);

      this.__emit('change', value);
    }
  },
  render: function render() {
    var _getOptionProps = getOptionProps(this),
        count = _getOptionProps.count,
        allowHalf = _getOptionProps.allowHalf,
        prefixCls = _getOptionProps.prefixCls,
        disabled = _getOptionProps.disabled,
        tabindex = _getOptionProps.tabindex;

    var sValue = this.sValue,
        hoverValue = this.hoverValue,
        focused = this.focused;
    var _this$$attrs = this.$attrs,
        className = _this$$attrs.class,
        style = _this$$attrs.style;
    var stars = [];
    var disabledClass = disabled ? "".concat(prefixCls, "-disabled") : '';
    var character = getComponent(this, 'character');
    var characterRender = this.characterRender || this.$slots.characterRender;

    for (var index = 0; index < count; index++) {
      var starProps = {
        index: index,
        count: count,
        disabled: disabled,
        prefixCls: "".concat(prefixCls, "-star"),
        allowHalf: allowHalf,
        value: hoverValue === undefined ? sValue : hoverValue,
        character: character,
        characterRender: characterRender,
        focused: focused,
        onClick: this.onClick,
        onHover: this.onHover,
        key: index,
        ref: "stars".concat(index)
      };
      stars.push(_vue.createVNode(Star, starProps, null));
    }

    return _vue.createVNode("ul", {
      "class": classNames(prefixCls, disabledClass, className),
      "style": style,
      "onMouseleave": disabled ? noop : this.onMouseLeave,
      "tabindex": disabled ? -1 : tabindex,
      "onFocus": disabled ? noop : this.onFocus,
      "onBlur": disabled ? noop : this.onBlur,
      "onKeydown": disabled ? noop : this.onKeyDown,
      "ref": "rateRef",
      "role": "radiogroup"
    }, [stars]);
  }
};