import * as React from 'react';
import IReactComponentProps from '../../../common/structures/IReactComponentProps';
import styles from './RadioButtonGroup.scss';
import classNames from 'classnames';

export interface RadioButtonProps extends IReactComponentProps<HTMLInputElement> {
	value: string;
	label: string;
	/** Name is only optional when using RadioButtonGroup. */
	name?: string;
    onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
	checked?: boolean;
    disabled?: boolean;
}

export const RadioButton = (props : RadioButtonProps) => {
	const { label, id, value, name, onChange, disabled, checked, className, ...restProps } = props;

    return (
        <div {...restProps} className={classNames(className, styles.RadioButton, {
			[styles.RadioButton_Disabled]: disabled,
		})}>
            <input
                type="radio"
                id={id}
                name={name}
                value={value}
                onChange={onChange}
                disabled={disabled}
                className="radio-input"
				checked={checked}
            />
            <label htmlFor={id}>
				<span className={styles.RadioButton_Graphics} aria-hidden />
                {label}
            </label>
        </div>
    );
};

interface RadioButtonGroupProps extends IReactComponentProps {
    name: string;
	legend: string;
    onChange?: (value: string) => void;
	/** Currently selected value. Not passing this creates an uncontrolled button group. */
    value?: string;
    disabled?: boolean;
	/** Useful for temporarily unchecking RadioButtonGroup button while disabled */
	uncheckWhenDisabled?: boolean;
    children: React.ReactElement<RadioButtonProps>[] | React.ReactElement<RadioButtonProps>;
}

export const RadioButtonGroup = (props: RadioButtonGroupProps) => {
    const {
		name,
		value,
		onChange,
		disabled,
		children,
		className,
		legend,
		uncheckWhenDisabled,
		...restProps
	} = props;

    const [internalValue, setInternalValue] = React.useState(value);

    React.useEffect(() => {
        if (value !== undefined) {
            setInternalValue(value);
        }
    }, [value]);

    const isControlled = value !== undefined;

    const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        if (!isControlled) {
            setInternalValue(event.target.value);
		}

		onChange?.(event.target.value);
    };

    const renderChildren = () => {
        return React.Children.map(children, child => {
            if (React.isValidElement(child)) {
                const checked = !(disabled && uncheckWhenDisabled) && child.props.value === (isControlled ? value : internalValue);

                return React.cloneElement(child, {
                    key: `${name}-${child.props.value}`,
                    name,
                    onChange: handleChange,
                    disabled: disabled || child.props.disabled,
                    checked,
                    id: `${name}-${child.props.value}`
                });
            }
            return child;
        });
    };

    return (
        <fieldset role="radiogroup" className={classNames(className, styles.RadioButton_Group)} {...restProps}>
			<legend>{legend}</legend>
            {renderChildren()}
        </fieldset>
    );
};
