/**
 * BeforeAfter Component
 * Description: Three ways to show a course output - draggable comparison,
 *              small-source pair, or a single image
 * Dependencies: None
 */

window.BeforeAfter = ({ item, labels }) => {
    const { useState, useEffect, useRef, useCallback } = React;
    const [activeAfterIndex, setActiveAfterIndex] = useState(0);
    const ref = useRef(null);
    const dragging = useRef(false);

    // Reset variant index when item changes
    useEffect(() => {
        setActiveAfterIndex(0);
    }, [item.k]);

    // A missing file must not leave a broken-image glyph in a dark panel
    const hideBroken = (e) => { e.target.style.visibility = 'hidden'; };

    // Images are natively draggable, and that native drag hijacks the pointer
    // mid-gesture - you grab the divider and the browser hands you a ghost of
    // the picture instead. Synthetic pointer events never trigger it, so this
    // only ever shows up under a real mouse.
    const noDrag = (e) => e.preventDefault();

    const setPos = useCallback((pct) => {
        const node = ref.current;
        if (!node) return;
        const clamped = Math.max(0, Math.min(100, pct));
        node.style.setProperty('--pos', clamped + '%');
        node.setAttribute('aria-valuenow', Math.round(clamped));
    }, []);

    const fromEvent = useCallback((e) => {
        const node = ref.current;
        if (!node) return;
        const rect = node.getBoundingClientRect();
        setPos(((e.clientX - rect.left) / rect.width) * 100);
    }, [setPos]);

    const onDown = (e) => {
        dragging.current = true;
        e.currentTarget.setPointerCapture(e.pointerId);
        fromEvent(e);
    };
    const onMove = (e) => { if (dragging.current) fromEvent(e); };
    const onUp = (e) => {
        dragging.current = false;
        try { e.currentTarget.releasePointerCapture(e.pointerId); } catch (err) { /* already released */ }
    };
    const onKey = (e) => {
        const node = ref.current;
        if (!node) return;
        const cur = parseFloat(node.style.getPropertyValue('--pos')) || 50;
        if (e.key === 'ArrowLeft') { setPos(cur - 4); e.preventDefault(); }
        if (e.key === 'ArrowRight') { setPos(cur + 4); e.preventDefault(); }
    };

    const activeImage = (item.afters && item.afters[activeAfterIndex]) || item.k;

    if (item.m === 'slider' && item.before) {
        return (
            <div ref={ref} className="ba" tabIndex={0} role="slider"
                 aria-valuemin={0} aria-valuemax={100} aria-valuenow={50}
                 aria-label={item.t} style={{ '--pos': '50%' }}
                 onPointerDown={onDown} onPointerMove={onMove}
                 onPointerUp={onUp} onPointerCancel={onUp} onKeyDown={onKey}>
                <img src={window.ImageUtils.getImagePath(activeImage)} alt={item.t} onError={hideBroken}
                     draggable={false} onDragStart={noDrag} />
                <div className="ba-clip">
                    <img src={window.ImageUtils.getImagePath(item.before)} alt="" onError={hideBroken}
                         draggable={false} onDragStart={noDrag} />
                </div>
                <div className="ba-line"></div>
                <div className="ba-grip">&#8596;</div>
                <span className="ba-tag l">{labels.before}</span>
                <span className="ba-tag r">{labels.after}</span>
                {item.afters && item.afters.length > 1 ? (
                    <div className="stage-variants" onPointerDown={(e) => e.stopPropagation()}>
                        {item.afters.map((_, idx) => (
                            <button
                                type="button"
                                key={idx}
                                className={idx === activeAfterIndex ? 'on' : ''}
                                onClick={(e) => { e.stopPropagation(); setActiveAfterIndex(idx); }}
                                aria-label={`Variant ${idx + 1}`}
                            >
                                {idx + 1}
                            </button>
                        ))}
                    </div>
                ) : null}
            </div>
        );
    }

    return (
        <React.Fragment>
            <img className="ba-main" src={window.ImageUtils.getImagePath(activeImage)} alt={item.t}
                 onError={hideBroken} draggable={false} onDragStart={noDrag} />
            {item.src ? (
                <img className="stage-src" src={window.ImageUtils.getImagePath(item.src)}
                     alt={labels.sourceShort} title={labels.sourceShort} onError={hideBroken}
                     draggable={false} onDragStart={noDrag} />
            ) : null}
            {item.afters && item.afters.length > 1 ? (
                <div className="stage-variants">
                    {item.afters.map((_, idx) => (
                        <button
                            type="button"
                            key={idx}
                            className={idx === activeAfterIndex ? 'on' : ''}
                            onClick={() => setActiveAfterIndex(idx)}
                            aria-label={`Variant ${idx + 1}`}
                        >
                            {idx + 1}
                        </button>
                    ))}
                </div>
            ) : null}
        </React.Fragment>
    );
};
