import {useEffect, useMemo, useState, useRef} from 'react';
import {Tooltip, Spin, AutoComplete, Tree} from 'antd';
import {ReloadOutlined} from '@ant-design/icons';

import { dispatch } from '../../../../../model';
import {highlightSearchContentByTerms} from '../../../../../util';

import '../../Define/Component/DefineTree.less';

const {Option} = AutoComplete;

const ManageTree = (props) => {
  const {onClick} = props;
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState();
  const [options, setOptions] = useState([]);
  const [keyword, setKeyword] = useState('');
  const [expandedKeys, setExpandedKeys] = useState([]);
  const [selectedKeys, setSelectedKeys] = useState([]);
  const [autoExpandParent, setAutoExpandParent] = useState(false);

  const selectedKeysRef = useRef([]);

  useEffect(() => {
    getTreeNodes();
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  const treeData = useMemo(() => {
    const loop = (data) =>
      (data||[]).map((item) => {
        if (item.children) {
          return {
            title: item.name||'',
            key: item._id||'',
            origin: item,
            children: loop(item.children),
          };
        }

        return {
          title: item.name||'',
          key: item._id||'',
        };
      });

    return loop(data);
  }, [data])

  const treeList = useMemo(() => {
    const generateList = (data, list, path = null) => {
      (data||[]).forEach(node => {
        const {_id, name} = node;

        const currentPath = path ? `${path}/${name}` : name;
        list.push({key: _id, title: currentPath});
        if (node.children) {
          generateList(node.children, list, currentPath);
        }
      });
    };

    const newTreeList = [];
    generateList(data, newTreeList);
    
    return newTreeList;
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [data])

  const getTreeNodes = () => {
    setLoading(true);
    dispatch({
      type: 'msd.getMgrTreeNodes',
      callback: (data) => {
        setLoading(false);
        setData(data||[]);

        const firstModelNodeId = findFirstModelNode(data||[]);

        if ((selectedKeysRef.current||[]).length===0 && (data||[]).length>0) {
          onTreeSelect([firstModelNodeId]);
        }

        if ((expandedKeys||[]).length===0 && (data||[]).length>0) {
          setExpandedKeys([firstModelNodeId]);
          setAutoExpandParent(true);
        } else {
          setExpandedKeys(Array.from(new Set([...expandedKeys, ...selectedKeysRef.current])));
          setAutoExpandParent(true);
        }
      },
      error: () => {
        setLoading(false);
      }
    })
  }

  const onRefreshClick = () => {
    getTreeNodes();
  }

  const onAutoCompleteSearch = (searchText) => {
    setKeyword(searchText);
    setOptions(treeList.filter(item => item.title.indexOf(searchText)!==-1));
  };

  const onAutoCompleteSelect = (value, option) => {
    const paths = value.split('/');
    setKeyword(paths[paths.length-1]);

    if (isModelNode(option.key)) {
      onTreeSelect([option.key]);
    }

    setExpandedKeys(Array.from(new Set([...expandedKeys, option.key])));
    setAutoExpandParent(true);
  };

  const onAutoCompleteClear = () => {
    setKeyword('');
  }

  const onTreeExpand = (expandedKeys) => {
    setExpandedKeys(expandedKeys);
    setAutoExpandParent(false);
  }

  const onTreeSelect = (selectedKeys, e = null) => {
    if (selectedKeys.length === 0) {
      return;
    }

    if (e && e?.node && !isModelNode(e?.node?.key)) {
      return;
    }

    setSelectedKeys(selectedKeys);
    selectedKeysRef.current = selectedKeys;
    onClick && onClick(selectedKeys[0]);
  }

  const isModelNode = (value) => {
    return ((value||'').indexOf('Model=') !== -1);
  }

  const findFirstModelNode = (values) => {
    const generateList = (data, list) => {
      (data||[]).forEach(node => {
        list.push(node);
        if (node.children) {
          generateList(node.children, list);
        }
      });
    };

    const newTreeList = [];
    generateList(values, newTreeList);

    let firstModelNodeId = '';

    newTreeList.some(item => {
      if (isModelNode(item._id)) {
        firstModelNodeId = item._id;
      }

      return isModelNode(item._id);
    })

    return firstModelNodeId;
  }

  return (
    <div className='data-master-tree'>
      <div className='header p-3'>
        <Tooltip title="刷新目录" className='ml-2'>
          <ReloadOutlined 
            className='default' 
            onClick={onRefreshClick} 
            style={{ 
              fontSize:16,
              cursor:'pointer',
              flex: 1  
            }} 
          />
        </Tooltip>
        <div style={{flex: 3}} />
      </div>
      <div className='content p-3'>
        <Spin spinning={loading}>
          <AutoComplete
            className='content-search'
            allowClear
            value={keyword}
            onSelect={onAutoCompleteSelect}
            onSearch={onAutoCompleteSearch}
            onClear={onAutoCompleteClear}
          >
          {
            (options||[]).map((item, index) => {
              return (
                <Option key={item.key} value={item.title}>
                  <div style={{ whiteSpace: 'normal' }}>
                  {highlightSearchContentByTerms(item.title, [keyword])}
                  </div>
                </Option>
              );
            })
          }
          </AutoComplete>
          <Tree
            className='content-tree'
            showLine 
            showIcon={false} 
            autoExpandParent={autoExpandParent}
            treeData={treeData}
            onExpand={onTreeExpand}
            onSelect={onTreeSelect}
            expandedKeys={expandedKeys}
            selectedKeys={selectedKeys}
          />
        </Spin>
      </div>  
    </div>
  );
}

export default ManageTree;