import React, { useState, useEffect, useCallback,useMemo,Component } from 'react';
import {batch, shallowEqual,connect, useSelector, useDispatch} from 'react-redux'
import * as Common from './common'
import * as Drag from './Drag'
import * as Shared from 'placeholder-shared'
import * as Steps from './Steps2'
import * as Antd from 'antd'
import * as Step from './Step'
import * as LoadSourceTable from './LoadSourceTable'
import * as StepMenu from './StepMenu'
import * as Lineage from './Lineage'
import './Palette.scss'
import * as Data from './Data';

import {
    PartitionOutlined,
    DownOutlined,
    CloseOutlined,
    DatabaseOutlined,
    ClockCircleOutlined,
    PlayCircleOutlined,
    CodeOutlined,
    CheckOutlined,
    AntDesignOutlined,
    PlusCircleOutlined
} from '@ant-design/icons';
import { result } from 'lodash';

type PaletteItemProps = {
    displayName:string|React.ReactNode;
    name:string;
}
const PaletteItem = (props:PaletteItemProps) => {
    const dispatch = useDispatch()
    const {displayName, name} = props;
    const dragPayload = {
        'type': Drag.DragPayloadType.palette,
        name
    }
    const onDragStart = (e) => {
        dispatch(Shared.State.changeUIState('dragStep',
          dragPayload))
        

    }
    const onDragEnd = (e) =>{
        dispatch(Shared.State.changeUIState('dragStep',
          null))
    }

    return <Common.DivWithClassName draggable={true} onDragStart={onDragStart} onDragEnd={onDragEnd} className=''>
        {displayName}
    </Common.DivWithClassName>
}

 type PaletteProps = {

}

const getKey = (database,dataset, table) => {
    if (!database||!dataset || !table)
        return ''
    return `${database}-${dataset}-${table}`
}

export const AddJoinModal = (props:any)=>{
    const isAddJoinModalVisible = useSelector(state => (state as any).UIState.isAddJoinModalVisible)
    const dispatch = useDispatch();
    const nameAlreadyExistsCB = StepMenu.useNameAlreadyExistsCB();
    const onViewDependencies = StepMenu.useViewDependencies()
    const createJoinQueryThunk = Step.useCreateJoinQueryThunk(nameAlreadyExistsCB)

    const handleCancel = (e)=>{
        dispatch(Shared.State.changeUIState('isAddJoinModalVisible', false));
    }
    const handleOk = (e) => {
        dispatch((dispatch, getState) => {
            dispatch(createJoinQueryThunk);
        })
    }
    return (<Antd.Modal
          title="Choose a Join Creation Method..."
          visible={isAddJoinModalVisible}
          onOk={handleOk}
          onCancel={handleCancel}
        >
            <Antd.Radio defaultChecked={true} disabled={false}>
              Inner Join SQL template (write your own Join Keys in SQL statement)
            </Antd.Radio>
            <Antd.Radio defaultChecked={false} disabled={true}>
                Wizard (use wizard to select Join Keys)
            </Antd.Radio>
        </Antd.Modal>)
}

export const AddSourceModal = (props:any) =>{
    const [tableTitleBreadcrumbs, setTableTitleBreadcrumbs] = useState([]);
    const nameAlreadyExistsCB = StepMenu.useNameAlreadyExistsCB();
    const sourceAlreadyExistsCB = StepMenu.useSourceAlreadyExists()
    const stepCounter = useSelector(state => (state as any).currentStep)
    const [dataToShow, setDataToShow] = useState([[], []]);
    const [checkedKeys, setCheckedKeys] = useState([])
    const [leafKeys, setLeafKeys] = useState([]);
    const [tables, setTables] = useState(null)
    const dispatch = useDispatch()
    const userConfig:Shared.State.IUserConfig = useSelector(state=> (state as any).userConfig)
    const addSourceModalVisibility = useSelector(state =>(state as any).UIState.isAddSourceModalVisible);    
    useEffect( () => {
        if (addSourceModalVisibility) {
            setCheckedKeys([])
            setLeafKeys([])
        }
    },[addSourceModalVisibility,setCheckedKeys,setLeafKeys])
    
    const filters = StepMenu.useGetFiltering()
    const handleClick = (e: any) => {
        const treeDataThunk = (dispatch, getState) =>{
            batch(() => {
                let leafKeysTest = [];
                for (let i = 0; i < checkedKeys.length; i++) {
                    let sourceOpParams  = StepMenu.parseSourceOperation(checkedKeys[i]);
                    if (sourceOpParams.database && sourceOpParams.dataset && sourceOpParams.table) {
                        const [nameExists, conflictingName, conflictingStepCounter] = nameAlreadyExistsCB(stepCounter, sourceOpParams.table)
                        const [sourceAlreadyExists, sourceConflictingName] = sourceAlreadyExistsCB(sourceOpParams.table)
                        if (sourceAlreadyExists) {
                            Antd.message.error(<span>Cannot add  <b>{sourceOpParams.table}</b> because the table name {sourceConflictingName} already exists in the graph.</span>
                            )
                        }
                        else if (nameExists) {
                            if (!filters.length) {
                                Antd.message.error(<span>Cannot add  <b>{sourceOpParams.table}</b> because the table name {conflictingName} already exists in the graph.</span>
                                )
                            }
                            else {
                                dispatch(Shared.State.moveToLineageGroup({ [conflictingStepCounter as any]: true }, filters))
                            }
                        }
                        else {
                            let treeData = getState().treeData[1];
                            let newStepCounter = Step.getNextID(treeData)
                            dispatch(Shared.State.getCreateStepAction(new Shared.Runner.SourceOperation(), 1, newStepCounter, "", true, 0, 0))
                            dispatch(Shared.State.getUpdateStepOperationAction(newStepCounter, 'database', sourceOpParams.database, false))
                            dispatch(Shared.State.getUpdateStepOperationAction(newStepCounter, 'dataset', sourceOpParams.dataset, false))
                            dispatch(Shared.State.getUpdateStepOperationAction(newStepCounter, 'table', sourceOpParams.table, false))
                            dispatch(Shared.Runner.runStep(newStepCounter))
                            if (filters.length){
                                dispatch(Shared.State.moveToLineageGroup({ [newStepCounter]: true }, filters))
                            }
                        }
                    }
                }
                
                dispatch(Shared.State.changeUIState('isAddSourceModalVisible', false));
            })
        }
        dispatch(treeDataThunk);
    }
  const showModal = (e: any) => { 
        dispatch(Shared.State.changeUIState('isAddSourceModalVisible', true));
    }
  const hideModal = (e: any) => { 
      dispatch(Shared.State.changeUIState('isAddSourceModalVisible', false));
    }

  const onSelect = (selectedKeys: any, info: any) => {
   // console.log('selected', selectedKeys, info); //call Shared.Snowflake.runGetRows(), this returns a QueryResult promise, 
    //call LoadSourceTable.getData(), 
    //which returns the columns and names adn then pass that to HotTableWrapper
    const sourceOp = new Shared.Runner.SourceOperation();
    const sourceOpParams  = StepMenu.parseSourceOperation(selectedKeys[0]);
    Object.assign(sourceOp, sourceOpParams);
    setTableTitleBreadcrumbs([sourceOpParams.database, sourceOpParams.dataset, sourceOpParams.table])
    const queryResultProm = Shared.Snowflake.runGetRows(null, userConfig, sourceOp);
    queryResultProm.then((queryResult: Shared.Runner.QueryResult)=>{
        const [rows, columns] = Data.getData([], queryResult)
        setDataToShow([rows,columns])
    })
  };

  const onCheck = (checkedKeys: any, info: any) => {
    //console.log('onCheck', checkedKeys, info);
    let leafKeysTest = [];
    for (let i = 0; i < checkedKeys.length; i++) {
        let sourceOpParams  = StepMenu.parseSourceOperation(checkedKeys[i]);
        if(sourceOpParams.database && sourceOpParams.dataset && sourceOpParams.table){
            leafKeysTest.push(checkedKeys[i]);
        }
    }
    setCheckedKeys(checkedKeys)
    setLeafKeys(leafKeysTest);
  };

  useEffect(() => {
    /*
    console.log("running get sources")
    Shared.Runner.runQuery({}, 'listTables', {}).then((tables) => {
        console.log("got tables", tables)
        setTables(tables)
    })
    */
   Shared.Snowflake.runListTables(userConfig).then((tables:
       Shared.Runner.TableList) => {
       setTables(tables)
   }).catch((err) => {
       Antd.message.error(<span>Unable to get tables {err.error.message}</span>
       )
   }
   )
}, [userConfig])

  const treeData = useMemo(() => {
    return !tables ? null : Object.keys(tables).map((database) => {
        return {
            title: database, key: database, isLeaf: false, checkable: false,
            children:
                Object.keys(tables[database]).map((schema) => {
                    return {
                        title: schema,
                        key: `${database}-${schema}`,
                        isLeaf: false,
                        checkable: false,
                        children: tables[database][schema].map((table) => {
                            return {
                                title: table,
                                key: getKey(database, schema, table),
                                isLeaf: true
                            }
                        })
                    }
                })
        }
    })
}, [tables])
    const hotSettings = useMemo(() => {
        return Data.getHotSettings(dataToShow[0], dataToShow[1], '100%', '100%')
    }, [dataToShow])
    const isOkButtonDisabled = (leafKeys.length === 0) ? true : false;
    return (
      <Antd.Modal
      centered
        title="Add Sources to SQL Pipeline"
        width={"95%"}
        okText={`Add ${leafKeys.length} sources`}
        visible={addSourceModalVisibility}
        onOk={handleClick}
        okButtonProps={{ disabled: isOkButtonDisabled }}
        onCancel={hideModal}
      >
          <Common.DivWithClassName style={{height:'65vh'}} className='rowFlexBox flexGrow'>
              <Common.DivWithClassName className='width300px positionRelative flexStay overflowYScroll'>
              <Common.DivWithClassName className='positionAbsolute '>
            <Antd.Tree
              checkable
              onSelect={onSelect}
              onCheck={onCheck}
              treeData={treeData}
            />
               </Common.DivWithClassName>
            </Common.DivWithClassName>
                <Common.DivWithClassName className='paddingSides5 columnFlexBox flexGrow'>
                <BreadCrumbWrapper tableTitleBreadcrumbs={tableTitleBreadcrumbs} />
                {hotSettings.data.length !== 0 &&
                    <Data.HotTableWrapper settings={hotSettings} />
                }
                {hotSettings.data.length === 0 &&
                    <Antd.Empty image={Antd.Empty.PRESENTED_IMAGE_SIMPLE} className='justifySelfCenter flexGrow alignSelfCenter minHeightZero overflowHidden' description={<>Select a Data Source to preview data.</>}> </Antd.Empty>
                    
                }
                </Common.DivWithClassName>
                {/*<Antd.Table dataSource={[]} columns={[]} style={{ width: '100%', height: '100%' }} />*/}
            </Common.DivWithClassName>
      </Antd.Modal>
  );
}

export const BreadCrumbWrapper = (props: any) =>{
    const {tableTitleBreadcrumbs} = props;
    const listItems = tableTitleBreadcrumbs.map((item, index) => <Antd.Breadcrumb.Item key={`${item}+${index}`}>{item}</Antd.Breadcrumb.Item>
);
    return <Antd.Breadcrumb>{listItems}</Antd.Breadcrumb>
}


export const Palette = (props:PaletteProps) => {
    const currentTask = useSelector(state => (state as any).currentTask)
    const currentStep = useSelector(state => (state as any).currentStep)
    const currentStepGraph = useSelector(state => (state as any).currentStepGraph)
    const currentStepGraphData = useSelector(state => (state as any).steps[currentStepGraph])
    const treeData = useSelector(state => (state as any).treeData[1])
    const dispatch = useDispatch()
    const createQueryCB = Step.useCreateQueryStep()
    const onAddSQLStep = (e: any) => {
        dispatch(Shared.State.changeUIState('isAddSqlActivated', true))
    }
    const onCancel = (e:React.MouseEvent) => {
        batch(() => {
            dispatch(Shared.State.changeUIState('isAddSqlActivated', false))
            dispatch(Shared.State.getClearSQLSelectAction())
        })
    }
    const isAddSqlActivated = useSelector(state => (state as any).UIState.isAddSqlActivated)
    const addSqlSelect = useSelector(state => (state as any).addSQLSelect)
    const isAddSourceModalVisible = useSelector(state => (state as any).UIState.isAddSourceModalVisible)
    const canCreateQuery = addSqlSelect && Object.keys(addSqlSelect).length > 0;
    const onCreateQuery = (e: any) => {
        //create query
        createQueryCB(Object.keys(addSqlSelect))
        batch(() => {
            dispatch(Shared.State.changeUIState('isAddSqlActivated', false))
            dispatch(Shared.State.getClearSQLSelectAction())
        }
        )
    }
    let children = null;

    const steps = useSelector(state => (state as any).steps)

    const graphViewMode = useSelector(state => Shared.Common.getValueSafe(state, ['UIState', 'graphViewMode'], 'graph'))
    const onRunResult = useCallback((stepCounter) => {

    }, [])
    const onRunAll = useCallback((e:any)=> {
        dispatch(Shared.Runner.PlayTaskThunk(1, onRunResult ,null))
    },[dispatch,onRunResult])
    const menu = <>
        {isAddSourceModalVisible == true && <AddSourceModal />}
        <AddJoinModal />
        {/*}
            <AddSourceModal />
            {/*
            <Common.DivWithClassName key='Divider1' className='height100Percent VerticalDivider'>
            </Common.DivWithClassName>

            <Antd.Button key='CreateModel' icon={<PlusCircleOutlined />} size='small' onClick={onCreateQuery}>Create Model</Antd.Button>
            <Antd.Button key='QueryExistingModel' icon={<CodeOutlined />} size='small' disabled={!isGenerateAllowed} onClick={onAddSQLStep}>Create Model</Antd.Button>

        */}
    </>

/*
    const viewSelector = <Antd.Space>
        <Antd.Typography.Text strong>View as: </Antd.Typography.Text>
        <Antd.Radio.Group size='small' value={graphViewMode} onChange={(e) => {
            dispatch(Shared.State.changeUIState('graphViewMode', e.target.value))

        }}>
            <Antd.Radio value={'graph'}>Graph</Antd.Radio>
            <Antd.Radio value={'datasets'}>Datasets</Antd.Radio>
        </Antd.Radio.Group>
        </Antd.Space>
        */

    children = <>
        {menu}
        <Lineage.LineageControls/>
        <Common.DivWithClassName className='floatRight rowFlexBox alignItemsCenter'>
            <Antd.Space direction='horizontal'>
                <Antd.Button type='primary' size={'small'} onClick={onRunAll}>
                    <PlayCircleOutlined /> Run All
                        </Antd.Button>
            </Antd.Space>
        </Common.DivWithClassName>
    </>
    return <Common.DivWithClassName onMouseDown={
        (e) => {
            e.stopPropagation()
        }}
        className=
        {Common.classNames({
            rowFlexBox: true,
            PaletteContainer: true,
            width100Percent: true,
            isAddSQLActivated: isAddSqlActivated
        })}>
        {children}
    </Common.DivWithClassName >
}

export const StatePalette = Palette
