import React, { useState } from 'react';
import PropTypes from 'prop-types';
import './styles/ratingInput.scss';
import Icon from '../icon/Icon';
import { createNamespace } from '../../tools/namingTools';
import { MAX_RATING } from '../../constants/ratings';

const n = createNamespace('RatingInput');

const RatingInput = ({
    rating,
    ratingScore,
    name,
    height,
    inputRef,
    i18n: {
        labels
    }
}) => {
    const [curHover, setHover] = useState(null);
    const [curValue, setValue] = useState(rating);

    // when hovering, display candidate value instead of set value
    const displayValue = curHover || curValue;

    // defaults to state if no change listener is defined in props
    const onChange = newValue => setValue(newValue);

    const renderRatings = () => [...Array(ratingScore).keys()].map(index => {
        const status = displayValue > index ? 'positive' : 'neutral';
        const iconModifiers = displayValue > index ? `rating${displayValue}` : '';
        const stars = index + 1;

        return (
            <span
                {...n('star').withTestId(status).props}
                key={`ratingStar${index}`}
                onMouseEnter={() => setHover(stars)}
                onClick={() => onChange(stars)}
                onKeyPress={() => onChange(stars)}
            >
                <Icon type="star" style={{ height: `${height}px` }} {...n(status, iconModifiers).props} />
            </span>
        );
    });

    let hiddenInput;
    if (inputRef) {
        hiddenInput = <input {...n('control', 'hidden').props} type="number" readOnly ref={inputRef} name={name} value={curValue || 0} />;
    }

    return (
        <div {...n('wrapper').props}>
            <div {...n('score').props} onMouseLeave={() => setHover(null)}>
                {renderRatings()}
                { displayValue && <span {...n('label').withTestId().props}>{labels[displayValue] || '&nbsp;'}</span> }
            </div>
            {hiddenInput}
        </div>
    );
};

RatingInput.propTypes = {
    rating: PropTypes.number,
    ratingScore: PropTypes.number,
    name: PropTypes.string,
    height: PropTypes.number,
    inputRef: PropTypes.func,
    i18n: PropTypes.shape({
        labels: PropTypes.shape({
            1: PropTypes.string,
            2: PropTypes.string,
            3: PropTypes.string,
            4: PropTypes.string,
            5: PropTypes.string
        })
    })
};

RatingInput.defaultProps = {
    rating: null,
    ratingScore: MAX_RATING,
    name: 'rating',
    height: null,
    inputRef: null,
    i18n: {
        labels: {
            1: 'Poor',
            2: 'Fair',
            3: 'Average',
            4: 'Good',
            5: 'Excellent'
        }
    }
};

export default RatingInput;
