import React, {useMemo, useCallback, useState, useEffect, useRef, useLayoutEffect} from 'react';
import {useSelector,useDispatch} from 'react-redux'
import * as Shared from 'placeholder-shared'
import * as Common from './common'
var classnames = require('classnames')

export enum DragPayloadType {
    step = 'step',
    leftBar = 'leftBar',
    palette = 'palette',
    port = 'port'
}
export interface DragPayload {
    type:DragPayloadType;
    stepCounter:number;
    taskID:number;
}

export const useChangeLayout = (defaultValue:number, uiStateKey:string) => {
    const value = useSelector((currentState) => (currentState as any).UIState[uiStateKey])
    const dispatch = useDispatch()
    let cb = useCallback((value: any) => {
        dispatch(Shared.State.changeUIState(uiStateKey,
            value))
    }, [dispatch,uiStateKey])
    return [value? value: defaultValue,cb];
}

export const useChangeDragInfo = (uiStateKey:string) => {
    const dispatch = useDispatch()
    let cb = useCallback((value: any) => {
        dispatch(Shared.State.changeUIState(uiStateKey,
            value))
    }, [dispatch,uiStateKey])
    return cb;
}

export type DragSourceProps = {
    className?:string;
    children:React.ReactNode;
    payload:any;
    onDragStart:(e:React.DragEvent)=>any;
    onDragEnd:(e:React.DragEvent)=>any;
    sourceID:any;
}

export const DragSourceContainer = (props:DragSourceProps)  => {
    const {className, children, payload, onDragStart, onDragEnd, sourceID} = props
    const onDragStartCB = useCallback((e:React.DragEvent) => {
        //e.stopPropagation()
        //console.log("drag starting", payload, sourceID)
        if (e.currentTarget == e.target) {
            e.dataTransfer.setData("application/json", JSON.stringify(payload))
        }
        onDragStart(e)
    }, [sourceID, payload, onDragStart])
    const onDragEndCB= useCallback((e:React.DragEvent) => {
        //console.log("drag ending", payload, sourceID)
        //e.stopPropagation()
        onDragEnd(e)
    }, [sourceID, payload,  onDragEnd ])
    
    return <Common.DivWithClassName onDragEnd={onDragEndCB} onDragStart={onDragStartCB} draggable={true} className={classnames("DragSource", className)}> 
        {children}
    </Common.DivWithClassName>
}

export type DropTargetProps = {
    className?:string;
    children:React.ReactNode;
    onDragOverEnter?:() =>any;
    onDragOverExit?:() => any;
    onDrop? : (e:React.DragEvent) =>any;
}
export const DropTargetContainer = (props:DropTargetProps) => {
    let {className, children, onDrop, onDragOverEnter, onDragOverExit} = props;
    let [isOver, setIsOver] = useState(false)
    const onDragOver = useCallback((e:React.DragEvent) => {
        e.stopPropagation();
        e.preventDefault();
        //console.log("in drag over", targetID)

        //e.stopPropagation()
        if (!isOver){
            //onDragOverEnter()
        }
    }, [isOver])
    const onDragEnter = useCallback((e:React.DragEvent) => {
        //console.log("in drag enter")
        //e.stopPropagation()
        onDragOverEnter && onDragOverEnter()

    }, [onDragOverEnter])
    const onDragLeave = useCallback((e:React.DragEvent) => {
        //console.log("in drag leave ")
        //e.stopPropagation()
        onDragOverExit && onDragOverExit()
    }, [onDragOverExit])
    const onDropCB = useCallback((e:React.DragEvent)=> {
        //console.log("in on drop")
        onDrop && onDrop(e)
    }, [onDrop])
    return <div className={classnames('DropTargetContainer', className)} onDrop={onDropCB} onDragEnter={onDragEnter} onDragLeave={onDragLeave} onDragOver={onDragOver} >
        {children}
    </div>

}