import {ChangeEvent, useState, useEffect, InputHTMLAttributes} from 'react';
import {fromEvent as rxFromEvent} from 'rxjs';
import cls from 'classnames';
import cn from './switch.module.styl';

export interface SwitchProps extends Pick<InputHTMLAttributes<HTMLInputElement>, 'id' | 'checked'> {
    onChange?(checked: boolean): void;
    preserveBackground: boolean;
    readOnly?: boolean;
}

export function Switch(props: Partial<SwitchProps>) {
    const {
        onChange = () => {},
        id,
        checked = false,
        preserveBackground = false,
        readOnly = false
    } = props;

    const [isToggleTouched, setIsToggleTouched] = useState<boolean>(false);

    /*
     ****************************************
     * Effect Hooks
     ****************************************
     */
    useEffect(() => {
        const sub = rxFromEvent(document, 'mouseup').subscribe(() => setIsToggleTouched(false));
        return () => sub.unsubscribe();
    }, []);

    /*
     ****************************************
     * Event Handlers
     ****************************************
     */
    function checkboxCheckedChangeHandler(evt: ChangeEvent<HTMLInputElement>) {
        if (!readOnly) onChange(evt.target.checked);
    }

    function toggleMouseDownHandler() {
        setIsToggleTouched(true);
    }

    function toggleMouseLeaveHandler() {
        setIsToggleTouched(false);
    }

    return (
        <span
            className={cls(cn.ffwdSwitch, {[cn.active]: checked, [cn.preserveBackground]: preserveBackground})}
            onMouseDown={toggleMouseDownHandler}
            onMouseLeave={toggleMouseLeaveHandler}
        >
            <span className={cls(cn.toggle, {touched: isToggleTouched})} />
            <input
                type="checkbox"
                id={id}
                className={cn.input}
                checked={checked}
                onChange={checkboxCheckedChangeHandler}
            />
        </span>
    );
}
