import React, { useContext, useEffect, useRef, useState, useCallback } from 'react';
import {Context as SchemeContext} from './SchemeContext';
import {Context as BlocksContext} from './Blocks';


export default Component => ({
    __ix,
    position,
    onMove,
    onMoveEnd,
    onMoveStart,
    ...props
}) => {
    const [[x, y], setPosition] = useState(position || []),
        cp = useRef([x, y]),
        {svg, zoom} = useContext(SchemeContext),
        {onSelect: onSelectBlocks} = useContext(BlocksContext),
        $box = useRef(null),
        coords = useRef([0,0,0,0]),
        eMouseMove = 'mousemove',
        eMouseUp = 'mouseup',
        eMouseLeave = 'mouseleave',
        onDrag = useCallback(e => {
            cp.current = [
                coords.current[2] + (zoom || 1) * (e.pageX - coords.current[0]),
                coords.current[3] + (zoom || 1) * (e.pageY - coords.current[1])
            ];
            setPosition(cp.current);
            onMove && onMove({x: cp.current[0], y: cp.current[1]});
        }, [zoom]),
        onMouseUp = useCallback(e => {
            onMoveEnd && onMoveEnd({x: cp.current[0], y: cp.current[1]});
            svg.current.removeEventListener(eMouseMove, onDrag);
            svg.current.removeEventListener(eMouseLeave, onMouseUp);
            svg.current.removeEventListener(eMouseUp, onMouseUp);            
        }, []),        
        onMouseDown = useCallback(e => {
            coords.current = [e.pageX, e.pageY, cp.current[0], cp.current[1]];
            svg.current.addEventListener(eMouseMove, onDrag);
            svg.current.addEventListener(eMouseLeave, onMouseUp);
            svg.current.addEventListener(eMouseUp, onMouseUp);
            onMoveStart && onMoveStart({x: cp.current[0], y: cp.current[1]});
            onSelectBlocks && onSelectBlocks(__ix);
        }, []);

    useEffect(() => (eMouseDown => {
        $box.current.addEventListener(eMouseDown, onMouseDown);
        return () => {
            $box.current.removeEventListener(eMouseDown, onMouseDown);
        }
    })('mousedown'), []);

    return (<g
        transform={`translate(${Math.floor(x || 0)+.5}, ${Math.floor(y || 0)+.5})`}    
        ref={$box}
    >
        <Component key={__ix} __ix={__ix} {...props} />
    </g>);
}