/* eslint-disable react/display-name */

import * as Immer from 'immer'
import * as Step from './Step'
import * as Common from './common'
import * as Steps from './Steps2'
import * as Palette from './Palette'
import * as Drag from './Drag'
import * as Shared from 'placeholder-shared'
import * as Antd from 'antd'
import * as Data from './Data'
import {shallowEqual, useSelector,useDispatch, connect} from 'react-redux'
import * as AntdIcon from '@ant-design/compatible'
import * as SQLStepMenu from './SQLStepMenu'
import {
    ThunderboltOutlined,
    CodeOutlined, DatabaseOutlined
  } from '@ant-design/icons';
import './Steps.scss'
    /*
export {
    PrepStep, IfStep, ParallelStep, ForEveryStep,RestStep, LoadFileStep, DBInputStep, DBOutputStep, JoinStep, FileInputStep 
}
*/
export const useChangeOperationArray = (stepCounter: number, keyPathHoldingArray:string) => {
    const dispatch = useDispatch()
    const arr = useSelector(state => {
        return Shared.Common.getValueSafe((state as any).steps[stepCounter].operation, keyPathHoldingArray, null)
    })
    return (modifyCB: (ops: any[]) => any[]) => {
        const newOps = modifyCB(arr)
        dispatch(Shared.State.getUpdateStepOperationAction(stepCounter, keyPathHoldingArray, newOps, true))
    }
}

export const useRemoveOperationArray = (stepCounter:number, keyHoldingArray:string) => {
    const changeCB = useChangeOperationArray(stepCounter, keyHoldingArray)
    return (index:number) => {
        const modifyCB = (ops: any[]) => {
            return Immer.produce(ops, (draftState) => {
                draftState.splice(index, 1)
            })
        }
        changeCB(modifyCB)
    }
}

export const useAddOperationArray = (stepCounter: number, keyHoldingArray:string) => {
    const changeCB = useChangeOperationArray(stepCounter, keyHoldingArray)
    return (newObj: any) => {
        const foo = stepCounter
        const bar = keyHoldingArray
        const modifyCB = (ops: any[]) => {
            return Immer.produce(ops, (draftState) => {
                draftState.push(newObj)
            })
        }
        changeCB(modifyCB)
    }
}

import React, {useMemo, useCallback, useState, useEffect, useRef, useLayoutEffect} from 'react';
import * as StepMenu from 'StepMenu'

export interface StepDescription {
    newOperation : () => any;
    step: (stepCounter) => React.ReactNode;
    stepMenu:() => React.ReactNode
    stepMenu2?:( stepCounter:number) => React.ReactNode
    dataView:(stepCounter:number) => React.ReactNode 
}
const StepDataView = (props: { stepCounter: number}) => {
    return <Data.StateDataView width={'100%'} height={220} className='flexStay' stepCounter={props.stepCounter}/>
}
const TabbedDataView = (props: { stepCounter: number, portIndexes: Shared.Runner.PortDescription[]}) => {
    const {portIndexes, stepCounter} = props
    const runResults = useSelector((state) => {
        const runResultDict = {}
        portIndexes.forEach((p: Shared.Runner.PortDescription) => {
            runResultDict[p.portIndex] = Shared.Common.getValueSafe((state as any), ['runResults', stepCounter, p.portIndex], {
                success: true, rows: [], fields: [], error: null
            })
        })
        return runResultDict;
    })
    return <Common.DivWithClassName className='borderSlightGreyTop card-container'><Antd.Tabs type='card' defaultActiveKey={portIndexes[0].portName} size={'small'}>
        {portIndexes.map((p: Shared.Runner.PortDescription) => {
            return <Antd.Tabs.TabPane tab={p.portName} key={p.portName}>
                <StepDataView stepCounter={stepCounter}  />
            </Antd.Tabs.TabPane>
        })
        }
    </Antd.Tabs>
    </Common.DivWithClassName>
}
export const StepDict:{[type:string]:StepDescription} = {
    [Shared.Runner.StepTypes.sourceInput]: {
        newOperation: () => {
            return new Shared.Runner.SourceOperation()
        },
        step: (stepCounter: number) => {
            return <StateSimpleStep inputsCount={0} outputsCount={1} type={'database'} stepCounter={stepCounter} />
        },
        stepMenu: () => {
            return <StepMenu.StateSourceStepMenu/>
        },
        dataView: (stepCounter: number) => {
            return <StepDataView  stepCounter={stepCounter} />
        }
    },
    [Shared.Runner.StepTypes.sql]: {
        newOperation: () => {
            return new Shared.Runner.SQLOperation()
        },
        step: (stepCounter: number) => {
            return <StateSimpleStep inputsCount={1} outputsCount={1} type={'code'} stepCounter={stepCounter} />
        },
        stepMenu: () => {
            return <SQLStepMenu.SQLStepMenuParent />
        },
        dataView: (stepCounter: number) => {
            return <StepDataView stepCounter={stepCounter} />
        }
    }
}

export type StepsProps = {

}

export const SimpleStep = (props :{inputsCount:number, outputsCount:number, stepCounter:number,type:string}) => {
    const {inputsCount, outputsCount, stepCounter, type} = props;
    const [onClick, onMouseDown] = Step.useShowStepOnClick(stepCounter)
    let portID = 0;
    const stepsSelect = useSelector(state => (state as any).stepsSelect)
    const addSQLSelect = useSelector(state => (state as any).addSQLSelect)
    const currentStep = useSelector(state => (state as any).currentStepGraph)
    const currentStepData = useSelector(state => (state as any).steps[stepCounter])
    const operation = useSelector(state => (state as any).steps[stepCounter].operation)
    const isSelected = currentStep == stepCounter || stepCounter in stepsSelect || stepCounter in addSQLSelect;
    const runResult = useSelector(state => (state as any).runResults[stepCounter])
    const swallow = (e)=>{
        e.stopPropagation()
        e.preventDefault()
        return;
        console.log("swallowing mouse down")
        e.preventDefault()
        //e.stopPropagation()
    }
    const onMouseUp = (e) => {
    }
    const getName = useCallback(() => {
        let name = Shared.Runner.getName(currentStepData)
        if (operation.type == Shared.Runner.StepTypes.sourceInput) {
            return <span><DatabaseOutlined/> {name}</span>
        }
        else {
            switch(operation.sqlType){
                case 'View':
                    return (<>
                        <span className='boringBadge boringBadgeView'>V</span> 
                        <span>{name}</span>
                    </>)
                    break;
                case 'Table':
                    return (<>
                        <span className='boringBadge boringBadgeTable'>T</span> 
                        <span>{name}</span>
                    </>)
                    break;
                default:
                    return (<>
                        <span className='boringBadge boringBadgeTable'><ThunderboltOutlined /></span>
                        <span>{name}</span>
                    </>)
            }   
        }
    },[currentStepData,operation.sqlType,operation.type])
    return <Common.DivWithClassName id={`Step-${stepCounter}`} onMouseUp={onMouseUp} onMouseDown={onMouseDown} onClick={onClick} className='rowFlexBox alignItemsCenter SimpleStep '>
        <Common.DivWithClassName className='rowFlexBox justifyContentSpaceEvenly'>
        {Array(inputsCount).fill(true).map((port) => {
            portID = portID + 1;
            return <Steps.PortWidgetUp key={portID} portIndex={portID  - 1} stepCounter={stepCounter}></Steps.PortWidgetUp>
        })}
        </Common.DivWithClassName>
        <Common.DivWithClassName className='columnFlexBox '>
            <Icon name={getName()} isCurrentStep={isSelected} />
        </Common.DivWithClassName>
        <Step.ResultsWidget runResult={runResult} />
        <Common.DivWithClassName className='rowFlexBox justifyContentSpaceEvenly'>
            {Array(outputsCount).fill(true).map((port) => {
                portID = portID + 1;
                return <Steps.PortWidgetDown key={portID} portIndex={portID - 1} stepCounter={stepCounter}></Steps.PortWidgetDown>
            })}
        </Common.DivWithClassName>
</Common.DivWithClassName>
}

export var StateSimpleStep = React.memo(SimpleStep)

export const Icon = (props:{
    name:any;
    isCurrentStep:boolean;

}) => {
    const {name,isCurrentStep} = props;
    return <Common.DivWithClassName className={
        Common.classNames({
            'CurrentStep': isCurrentStep,
            'NotCurrentStep': !isCurrentStep,
            'rowFlexBox': true,
            'justifyContentCenter': true,
            'nameBox':true,
        })}>
            {name}
    </Common.DivWithClassName>
}
export const HoverIcon = (props:{className?:string, type:string}) => {
    const {type,className} = props;
    const [hovered, setHovered] = useState(false)
    const onMouseEnterCB = useCallback((e: React.MouseEvent) => {
        console.log("on mouse enter")
        setHovered(true)
    }, [])
    const onMouseLeaveCB = useCallback((e: React.MouseEvent) => {
        console.log("on mouse leave")
        setHovered(false)
    }, [])
    const onDragOverCB = useCallback((e: React.MouseEvent) => {
        //console.log("on drag over")
        e.preventDefault()
        setHovered(true)
    }, [])
    const onDropCB = useCallback((e: React.MouseEvent) => {
        e.preventDefault()
        setHovered(false)
    }, [])
    const onDragLeaveCB = useCallback((e: React.MouseEvent) => {
        console.log("on drag leave")
        setHovered(false)
    }, [])
    return <Common.DivWithClassName onMouseEnter={onMouseEnterCB}
    onDrop={onDropCB}
    onDragOver={onDragOverCB}
    onDragLeave={onDragLeaveCB}
        onMouseLeave={onMouseLeaveCB}
        className={className}
    >
        <AntdIcon.Icon className='pointerEventsNone' type={type} theme={hovered ? 'twoTone' : 'outlined'} />
        </Common.DivWithClassName>
}
const onDrop = (e:React.MouseEvent) => {
    return <Common.DivWithClassName className=''>
        </Common.DivWithClassName>
}

const usePortDrop = (targetStepCounter:number, targetPortIndex:number) => {
    const dispatch = useDispatch()
    const dragStep = useSelector((state) => ((state as any).UIState.dragStep))
    const currentTask = useSelector((state) => ((state as any).currentTask))
    const onPortDropCB = useCallback((e:React.MouseEvent) => {
        const sourceStepCounter = dragStep.stepCounter, sourcePortIndex = dragStep.portIndex;
        const edge:Shared.TreeData.Edge = {
            sourcePort:{
                stepCounter:sourceStepCounter, 
                portIndex:sourcePortIndex
            },
            targetPort:{
                stepCounter:targetStepCounter, 
                portIndex:targetPortIndex
            },
        }
        //const edgeID = Shared.Data.getNextID(Shared.Data.IDType.edge)
        //dispatch(Shared.State.getCreateEdgeAction(currentTask, edge, edgeID))
    }, [dragStep,targetPortIndex, targetStepCounter,dispatch,currentTask])
    return onPortDropCB;
}

export const PortWidgetUp = (props:{className?:string,stepCounter:number, portIndex:number}) => {
    const {stepCounter,portIndex} = props
    const changeDragStep = Drag.useChangeDragInfo('dragStep')
    const onPortDropCB = usePortDrop(stepCounter, portIndex)
    const onDragStart = useCallback((e) => {
        changeDragStep({
            type: Drag.DragPayloadType.port,
            portIndex,
            stepCounter, x: 0, y: 0
        }
        )
    }, [changeDragStep])
    const onDragEnd = useCallback((e) => {
        changeDragStep(null)
    }, [changeDragStep])
    return <Common.DivWithClassName className={props.className}> <Drag.DropTargetContainer onDrop={onPortDropCB}>
        <Drag.DragSourceContainer
            sourceID={stepCounter}
            onDragStart={onDragStart}
            onDragEnd={onDragEnd}
            payload={{ stepCounter, type: Drag.DragPayloadType.port }}
        ><PortWidget stepCounter={stepCounter} portIndex={portIndex} type='left-circle' />
        </Drag.DragSourceContainer>
    </Drag.DropTargetContainer> 
    </Common.DivWithClassName>
}
export const PortWidgetDown = (props:{stepCounter:number, portIndex:number, className?:string}) => {
    const {stepCounter,portIndex} = props
    const changeDragStep = Drag.useChangeDragInfo('dragStep')
    const onDragStart = (e) => {
        changeDragStep({
            type: Drag.DragPayloadType.port,
            portIndex,
            stepCounter, x: 0, y: 0
        }
        )
    }
    const onDragEnd = (e) =>{
        changeDragStep(null)
    }
    return <Common.DivWithClassName className={props.className}><Drag.DragSourceContainer
        sourceID={stepCounter}
        onDragStart={onDragStart}
        onDragEnd={onDragEnd}
        payload={{ stepCounter, type: Drag.DragPayloadType.port }}
    ><PortWidget stepCounter={stepCounter} portIndex={portIndex} type='' />
    </Drag.DragSourceContainer>
    </Common.DivWithClassName>
}

type PortWidgetProps = {
    className?:string;
    type:string;
    stepCounter:number, 
    portIndex:number;
}
export const PortWidget = (props: PortWidgetProps) => {
    const {className,type,stepCounter,portIndex} = props
    return null;
    return <Common.DivWithClassName 
    id={`port-${stepCounter}-${portIndex}`}
    className={Common.classNames({
        [className]:className,
        'PortWidget':true,
        'alignSelfCenter':true,
        'positionRelative':true
    })}>
        <HoverIcon type={type}/>
    </Common.DivWithClassName>
}
