import React, {PureComponent} from 'react';
import {Input, message, Tree, Modal} from 'antd';
import {DeleteOutlined, EditOutlined, FileOutlined, PlusCircleOutlined, ExclamationCircleOutlined} from '@ant-design/icons';
import {contextMenu, Item, Menu} from 'react-contexify';
import 'react-contexify/dist/ReactContexify.min.css';
import {getNodeByKeyAndCallbackProcess} from '@/components/_utils/algorithmTools';
import {connect} from '@umijs/max';

const {Search} = Input;

@connect(({globaldata, loading}) => ({
    globaldata,
    loading: loading.models.globaldata,
}))
class AsyncTree extends PureComponent {
    state = {
        expandedKeys: ['000000000000'],
        autoExpandParent: true,
        selectedKeys: [],
        treeData: [],
        selectedTreeByRightClick: "",
        searchValue: '',
        dataList: [],
        display: "block",
    };

    constructor(props) {
        super(props);
        this.state.treeData = [
            {title: props.rootNodeName, id: '000000000000', key: '000000000000', value: '000000000000', levelcode: "000000000000"},
        ]
    }

    componentDidMount() {
        const {dispatch, getTreeMethod, reQueryParent} = this.props;
        if(!reQueryParent) {
            return
        }
        dispatch({
            type: 'globaldata/' + getTreeMethod,
            payload: {
                parentid: "#"
            },
            callback: (res) => {
                console.log(res)
                if (res.success == true && res?.list.length > 0) {
                    const temList = res.list?.map((item) => {
                        return {
                            key: item.id,
                            ...item
                        }
                    })
                    this.setState({
                        treeData: temList
                    })
                }
            }
        });
    }

    //展开收起
    onExpand = expandedKeys => {
        this.setState({
            expandedKeys,
            autoExpandParent: false,
        });
    };

    // 选中的树节点
    onSelect = (selectedKeys, {node}) => {
        const {checkedTreeChild} = this.props;
        this.setState({selectedKeys});
        if(checkedTreeChild) {
            checkedTreeChild(node);
        }
    };

    addMenuTreeNode = () => {
        const {handleModalVisible} = this.props;
        handleModalVisible(true, this.state.selectedTreeByRightClick, this.reLoadCurrentTreeNode);
    };

    updateMenuTreeNode = () => {
        const {handleUpdateModalVisible} = this.props;
        handleUpdateModalVisible(true, this.state.selectedTreeByRightClick, this.reLoadCurrentTreeNodeUpdate);
    };

    viewMenuTreeNode = () => {
        const {handleViewModalVisible} = this.props;
        handleViewModalVisible(true, this.state.selectedTreeByRightClick);
    };

    deleteMenuTreeNode = () => {
        const {handleDeleteRecord} = this.props;
        Modal.confirm({
            title: '你确定要删除吗?',
            icon: <ExclamationCircleOutlined />,
            content: '删除该节点后其子节点也会删除！这并不会删除该节点及其子节点的的关联数据',
            okText: '确认',
            cancelText: '取消',
            onOk: () => {
                handleDeleteRecord(this.state.selectedTreeByRightClick, this.reLoadCurrentTreeNodeDelete)
            },
        });

    };

    // 响应右键点击
    rightClickTreeNode = ({event, node}) => {
        event.preventDefault();
        contextMenu.show({
            id: 'menu_id',
            event: event,
            props: {
                foo: 'bar'
            }
        });

        if (node.key != '000000000000') {
            this.setState({
                selectedTreeByRightClick: node,
                display: "block",
            });
        } else {
            this.setState({
                selectedTreeByRightClick: node,
                display: "none",
            });
        }
    }

    // 右键菜单
    MyAwesomeMenu = () => (
        <Menu id='menu_id' theme="light" style={{zIndex: 1000}}>
            <Item onClick={this.addMenuTreeNode}>
                <PlusCircleOutlined style={{fontSize: 16, paddingTop: 3}}/>
                <span style={{paddingLeft: 10}}>添加</span>
            </Item>
            <Item onClick={this.updateMenuTreeNode} style={{display: this.state.display}}>
                <EditOutlined style={{fontSize: 16, paddingTop: 3}}/>
                <span style={{paddingLeft: 10}}>修改</span>
            </Item>
            <Item onClick={this.viewMenuTreeNode} style={{display: this.state.display}}>
                <FileOutlined style={{fontSize: 16, paddingTop: 3}}/>
                <span style={{paddingLeft: 10}}>查看</span>
            </Item>
            <Item onClick={this.deleteMenuTreeNode} style={{display: this.state.display}}>
                <DeleteOutlined style={{fontSize: 16, paddingTop: 3}}/>
                <span style={{paddingLeft: 10}}>删除</span>
            </Item>
        </Menu>
    );

    // 组装树数据
    updateTreeData(list, key, children) {
        return list.map(node => {
            if (node.key === key) {
                return {
                    ...node,
                    children,
                };
            } else if (node.children) {
                return {
                    ...node,
                    children: this.updateTreeData(node.children, key, children),
                };
            }
            return node;
        });
    }

    /**
     * 异步加载树数据
     * @param key
     * @param children
     * @returns {Promise<unknown>}
     */
    onLoadData = ({key, children}) => {
        const {dispatch, getTreeMethod} = this.props;

        const params = {
            parentid: key
        };

        return new Promise((resolve) => {
            // if (children) {
            //     resolve();
            //     return;
            // }
            dispatch({
                type: 'globaldata/' + getTreeMethod,
                payload: params,
                callback: (res) => {
                    if (res.success == true) {
                        const temList = res.list?.map((item) => {
                            return {
                                key: item.id,
                                ...item
                            }
                        })
                        this.setState({
                            treeData: this.updateTreeData(this.state.treeData, key, temList)
                        });
                    }
                    resolve();

                }
            });
        });
    };


    reLoadCurrentTreeNode = (treeNode, dropKey) => {
        const data = [...this.state.treeData];
        treeNode.key = treeNode.id;
        getNodeByKeyAndCallbackProcess(data, dropKey, (item) => {
            item.children = item.children || [];
            // where to insert 示例添加到尾部，可以是随意位置
            item.children.push(treeNode);
        });

        this.setState({
            treeData: data,
        });

    };


    reLoadCurrentTreeNodeUpdate = (treeNode, currentTreeNodeKey, parentTreeNodeKey) => {
        const data = [...this.state.treeData];

        getNodeByKeyAndCallbackProcess(data, parentTreeNodeKey, (item) => {
            item.children = item.children || {};
            item.children = item.children.map((item, key) => item.key == currentTreeNodeKey ? {...item, ...treeNode} : item)
            // item.children.push(treeNode);
        });
        this.setState({
            treeData: data,
        });
    }


    reLoadCurrentTreeNodeDelete = (currentTreeNodeKey) => {

        const data = [...this.state.treeData];
        getNodeByKeyAndCallbackProcess(data, currentTreeNodeKey, (item, index, arr) => {
            arr.splice(index, 1);
        });

        this.setState({
            treeData: data,
        });
    }

    // 搜索事件
    onChange = e => {
        const {treeData, dataList} = this.state;
        const {value} = e.target;
        const expandedKeys = dataList.map(item => {
                if (item.title.indexOf(value) > -1) {
                    return this.getParentKey(item.title, treeData);
                }
                return null;
            }).filter((item, i, self) => item && self.indexOf(item) === i);
        this.setState({
            expandedKeys,
            searchValue: value,
            autoExpandParent: true,
        });
    };

    getParentKey = (title, tree) => {
        let parentKey;
        for (let i = 0; i < tree.length; i++) {
            const node = tree[i];
            if (node.children) {
                if (node.children.some(item => item.title === title)) {
                    parentKey = node.key;
                } else if (this.getParentKey(title, node.children)) {
                    parentKey = this.getParentKey(title, node.children);
                }
            }
        }
        return parentKey;
    };

    generateList = data => {

        if (undefined == data) {
            return false;
        }

        for (let i = 0; i < data.length; i++) {
            const node = data[i];
            const {key, title} = node;
            this.state.dataList.push({key, title: title});
            if (node.children) {
                this.generateList(node.children);
            }
        }
    };

    onDrop = async info => {
        const dropKey = info.node.key;
        const dragKey = info.dragNode.key;
        const dropPos = info.node.pos.split('-');
        const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);

        const source_parent_id = info.dragNode.parentid;
        const source_levelcode = info.dragNode.levelcode;
        let new_levelcode = "";
        let dragKey_parent_id = "";
        let sequences = "";
        let sequencesArray = [];

        const data = [...this.state.treeData];

        // Find dragObject
        let dragObj;
        getNodeByKeyAndCallbackProcess(data, dragKey, (item, index, arr) => {
            arr.splice(index, 1);
            dragObj = item;
        });

        if (!info.dropToGap) {
            let ar;
            // Drop on the content 移动到未展开的节点里
            getNodeByKeyAndCallbackProcess(data, dropKey, (item, index) => {
                new_levelcode = item.levelcode + "/" + dragKey;
                dragKey_parent_id = item.key;
                ar = item.children || [];

                dragObj.levelcode = new_levelcode;
                dragObj.parentid = dragKey_parent_id;
                item.children = item.children || [];
                sequences = item.children.length;
                // where to insert 示例添加到尾部，可以是随意位置 push
                item.children.unshift(dragObj);
            });
            ar.forEach((item, index) => {
                let arrs = {
                    id: item.key,
                    sequences: index
                }
                sequencesArray.push(arrs);
            })
        } else if (
            (info.node.props.children || []).length > 0 && // Has children
            info.node.props.expanded && // Is expanded
            dropPosition === 1 // On the bottom gap
        ) {
            getNodeByKeyAndCallbackProcess(data, dropKey, (item) => {
                new_levelcode = item.levelcode + "/" + dragKey;
                dragKey_parent_id = item.key

                dragObj.levelcode = new_levelcode;
                dragObj.parentid = dragKey_parent_id;
                item.children = item.children || [];
                item.children.unshift(dragObj);
            });
        } else {
            let ar;
            let i;
            getNodeByKeyAndCallbackProcess(data, dropKey, (item, index, arr) => {
                new_levelcode = item.levelcode.replace(item.key, "") + dragKey;
                dragKey_parent_id = item.parentid

                dragObj.levelcode = new_levelcode;
                dragObj.parentid = dragKey_parent_id;
                ar = arr;
                i = index;
            });
            if (dropPosition === -1) {
                sequences = i;
                ar.splice(i, 0, dragObj);
            } else {
                sequences = i + 1;
                ar.splice(i + 1, 0, dragObj);
            }
            ar.forEach((item, index, arr) => {
                if(sequences <= index) {
                    let arrs = {
                        id: item.key,
                        sequences: index
                    }
                    sequencesArray.push(arrs);
                }
            })
        }

        const {dispatch, updateTreeNodeByDragUrl} = this.props;

        await dispatch({
            type: 'globaldata/' + updateTreeNodeByDragUrl,
            payload: {
                source_id: dragKey,
                source_parentid: source_parent_id,
                source_levelcode: source_levelcode,
                target_id: dragKey_parent_id,
                levelcode: new_levelcode,
                sequences: sequences,
                sequencesArray: sequencesArray
            },
            callback: async (res) => {
                if(res.success == true) {
                    message.success('修改成功');
                    await this.setState({
                        treeData: data,
                    });
                }

            }
        });

    }

    render() {
        const { height, modify } = this.props;
        const {autoExpandParent, expandedKeys, selectedKeys, treeData} = this.state;
        this.generateList(treeData);

        return (
            <div style={{float: 'left', width: '30%'}}>
                <Search style={{marginBottom: 8, width: '100%'}} placeholder={'请输入'}
                        onChange={this.onChange}/>
                <Tree
                    loadData={this.onLoadData}
                    onExpand={this.onExpand}
                    expandedKeys={expandedKeys}
                    autoExpandParent={autoExpandParent}
                    onSelect={this.onSelect}
                    selectedKeys={selectedKeys}
                    onRightClick={this.rightClickTreeNode}
                    draggable={modify}
                    onDrop={this.onDrop}
                    treeData={treeData}
                    height={height || 700}
                >
                </Tree>
                {modify ? this.MyAwesomeMenu() : null}
            </div>
        );
    }
}

export default AsyncTree;
