import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
import React, { useCallback, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import Star from '@rsuite/icons/legacy/Star';
import { useClassNames, useControlled, shallowEqualArray, SIZE, KEY_CODE } from '../utils';
import { transformValueToCharacterMap, transformCharacterMapToValue } from './utils';
import Character from './Character';
import Plaintext from '../Plaintext';
var defaultProps = {
  as: 'ul',
  classPrefix: 'rate',
  character: /*#__PURE__*/React.createElement(Star, null),
  cleanable: true,
  defaultValue: 0,
  max: 5,
  size: 'md'
};
var Rate = /*#__PURE__*/React.forwardRef(function (props, ref) {
  var Component = props.as,
      character = props.character,
      className = props.className,
      classPrefix = props.classPrefix,
      disabled = props.disabled,
      max = props.max,
      readOnly = props.readOnly,
      vertical = props.vertical,
      size = props.size,
      color = props.color,
      allowHalf = props.allowHalf,
      valueProp = props.value,
      defaultValue = props.defaultValue,
      cleanable = props.cleanable,
      plaintext = props.plaintext,
      onChange = props.onChange,
      renderCharacter = props.renderCharacter,
      onChangeActive = props.onChangeActive,
      rest = _objectWithoutPropertiesLoose(props, ["as", "character", "className", "classPrefix", "disabled", "max", "readOnly", "vertical", "size", "color", "allowHalf", "value", "defaultValue", "cleanable", "plaintext", "onChange", "renderCharacter", "onChangeActive"]);

  var _useControlled = useControlled(valueProp, defaultValue),
      value = _useControlled[0],
      setValue = _useControlled[1];

  var getCharacterMap = useCallback(function (v) {
    return transformValueToCharacterMap(typeof v !== 'undefined' ? v : value, max, allowHalf);
  }, [allowHalf, max, value]);

  var _useState = useState(getCharacterMap()),
      characterMap = _useState[0],
      setCharacterMap = _useState[1];

  var hoverValue = transformCharacterMapToValue(characterMap);

  var _useClassNames = useClassNames(classPrefix),
      merge = _useClassNames.merge,
      withClassPrefix = _useClassNames.withClassPrefix;

  var classes = merge(className, withClassPrefix(size, color, {
    disabled: disabled,
    readonly: readOnly
  }));
  var resetCharacterMap = useCallback(function () {
    setCharacterMap(getCharacterMap());
  }, [getCharacterMap]);
  useEffect(function () {
    // Update characterMap when value is updated.
    setCharacterMap(getCharacterMap(valueProp)); // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [valueProp]);
  var handleMouseLeave = useCallback(function (event) {
    resetCharacterMap();
    onChangeActive === null || onChangeActive === void 0 ? void 0 : onChangeActive(value, event);
  }, [onChangeActive, resetCharacterMap, value]);
  var handleChangeValue = useCallback(function (index, event) {
    var nextValue = transformCharacterMapToValue(characterMap);

    if (cleanable && value === nextValue && getCharacterMap(value)[index] === characterMap[index]) {
      nextValue = 0;
    }

    if (nextValue !== value) {
      setValue(nextValue);
      setCharacterMap(getCharacterMap(nextValue));
      onChange === null || onChange === void 0 ? void 0 : onChange(nextValue, event);
    }
  }, [characterMap, cleanable, getCharacterMap, onChange, setValue, value]);
  var handleKeyDown = useCallback(function (index, event) {
    var keyCode = event.keyCode;
    var nextValue = transformCharacterMapToValue(characterMap);

    if (keyCode === KEY_CODE.RIGHT && nextValue < max) {
      nextValue = allowHalf ? nextValue + 0.5 : nextValue + 1;
    } else if (keyCode === KEY_CODE.LEFT && nextValue > 0) {
      nextValue = allowHalf ? nextValue - 0.5 : nextValue - 1;
    }

    setCharacterMap(getCharacterMap(nextValue));

    if (keyCode === KEY_CODE.ENTER) {
      handleChangeValue(index, event);
    }
  }, [allowHalf, characterMap, getCharacterMap, handleChangeValue, max]);
  var handleChangeCharacterMap = useCallback(function (index, key, event) {
    var nextCharacterMap = characterMap.map(function (_item, i) {
      if (i === index && key === 'before' && allowHalf) {
        return 0.5;
      }

      return index >= i ? 1 : 0;
    });

    if (!shallowEqualArray(characterMap, nextCharacterMap)) {
      setCharacterMap(nextCharacterMap);
      onChangeActive === null || onChangeActive === void 0 ? void 0 : onChangeActive(transformCharacterMapToValue(nextCharacterMap), event);
    }
  }, [allowHalf, characterMap, onChangeActive]);
  var handleClick = useCallback(function (index, key, event) {
    handleChangeCharacterMap(index, key, event);
    handleChangeValue(index, event);
  }, [handleChangeCharacterMap, handleChangeValue]);

  if (plaintext) {
    return /*#__PURE__*/React.createElement(Plaintext, {
      localeKey: "notSelected",
      className: className
    }, value + "(" + max + ")");
  }

  return /*#__PURE__*/React.createElement(Component, _extends({
    role: "radiogroup",
    tabIndex: 0
  }, rest, {
    ref: ref,
    className: classes,
    onMouseLeave: handleMouseLeave
  }), characterMap.map(function (item, index) {
    return /*#__PURE__*/React.createElement(Character, {
      role: "radio",
      "aria-posinset": index + 1,
      "aria-setsize": max,
      "aria-checked": value === index + 1,
      key: index,
      status: item,
      disabled: disabled || readOnly,
      vertical: vertical,
      onClick: function onClick(key, event) {
        return handleClick(index, key, event);
      },
      onKeyDown: function onKeyDown(event) {
        return handleKeyDown(index, event);
      },
      onMouseMove: function onMouseMove(key, event) {
        return handleChangeCharacterMap(index, key, event);
      }
    }, renderCharacter ? renderCharacter(hoverValue, index) : character);
  }));
});
Rate.displayName = 'Rate';
Rate.defaultProps = defaultProps;
Rate.propTypes = {
  allowHalf: PropTypes.bool,
  character: PropTypes.node,
  classPrefix: PropTypes.string,
  cleanable: PropTypes.bool,
  defaultValue: PropTypes.number,
  disabled: PropTypes.bool,
  max: PropTypes.number,
  renderCharacter: PropTypes.func,
  readOnly: PropTypes.bool,
  size: PropTypes.oneOf(SIZE),
  value: PropTypes.number,
  vertical: PropTypes.bool,
  onChange: PropTypes.func,
  onChangeActive: PropTypes.func
};
export default Rate;