import React, { useState, useEffect, useContext } from "react";
import { Tooltip, Tree, Modal, Spin, Dropdown, Menu, Button, AutoComplete } from "antd";
import { PlusOutlined, SwapOutlined, ImportOutlined, UnorderedListOutlined, ReloadOutlined } from '@ant-design/icons';
import classnames from 'classnames';
import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify";

import UpdateTreeItemModal from './UpdateTreeItemModal';
import { dispatch } from '../../../../model'; 
import { showMessage, getQueryParam, highlightSearchContentByTerms, getDataModelerRole } from '../../../../util';
import { AnchorDirId, AnchorId, AnchorTimestamp, DataModelerRoleAdmin } from '../../../../util/constant';
import { AppContext } from "../../../../App";

import './ModelTree.less';
import 'react-contexify/dist/ReactContexify.css';

const { Option } = AutoComplete;

const viewModes = [
  {
    key: 'dir',
    name: '目录视角'
  },
  {
    key: 'state',
    name: '服务状态视角'
  }
];

const ModelTree = (props) => {

  const MENU_ID = 'model-tree';

  const { show } = useContextMenu({
    id: MENU_ID,
  });

  const { onSelect, onViewChange, refrence='', importStockModel, keyword, isOnlyEnding = false } = props;

  const { user, env } = useContext(AppContext);
  const [ loading, setLoading ] = useState(false);
  const [ treeData, setTreeData ] = useState(null);
  const [ item, setItem ] = useState(null);
  const [ prevItem, setPrevItem ] = useState(null);
  const [ visible, setVisible ] = useState(false);
  const [ type, setType ] = useState(null);
  const [ rootId, setRootId ] = useState('');
  const [ expandedKeys, setExpandedKeys ] = useState([]);
  const [ autoExpandParent, setAutoExpandParent ] = useState(false);
  const [ viewSelectedKey, setViewSelectedKey ] = useState(viewModes[0].key);
  const [ isSetRootId, setIsSetRootId ] = useState(true);
  const [ domains, setDomains ] = useState([]);
  const [ domainSelectedKey, setDomainSelectedKey ] = useState('');
  const [ currentRightClickDir, setCurrentRightClickDir ] = useState({});
  
  const [ searchKeyword, setSearchKeyword ] = useState('');
  const [ dataList, setDataList ] = useState([]);
  const [options, setOptions] = useState([]);

  const [modal, contextHolder] = Modal.useModal();

  const timestamp = getQueryParam(AnchorTimestamp, props.location?.search||'');
  const id = getQueryParam(AnchorId, props.location?.search||'');
  const did = getQueryParam(AnchorDirId, props.location?.search||'');

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

  useEffect(() => {
    if (refrence === 'recatalog') {
      getDirTreeData();
    } else {
      setViewSelectedKey(viewModes[0].key);
      onViewChange && onViewChange(viewModes[0].key);

      if ((id||'') !== '') {
        getDataModelLocationThenGetDirTreeData();
      } else if ((did||'') !== '') {
        getDirTreeData(did);
      } else {
        getDirTreeData();
      }  
    }

    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [timestamp])

  useEffect(() => {

    if (keyword!=='') {
      if (item && !prevItem) {
        setPrevItem(item);
      }

      setItem(null);
    } else {
      if (prevItem && !item) {
        setItem(prevItem);
        onSelect && onSelect(prevItem?.key||'');
        setPrevItem(null);
      }
    }

    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [ keyword ])

  // const getShowSyncAndDomains = () => {
  //   dispatch({
  //     type: 'datamodel.isSetRootDomainId',
  //     callback: data => {
  //       if (data === 'false') {
  //         dispatch({
  //           type: 'user.getDomains',
  //           callback: _data => {
  //             setDomains(_data||[]);
  //             setIsSetRootId(false);
  //           }
  //         });
  //       } else {
  //         setIsSetRootId(true);
  //       }
  //     }
  //   });
  // }

  const getDataModelLocationThenGetDirTreeData = () => {
    setLoading(true);
    dispatch({
      type: 'pds.getDataServiceLocation',
      payload: {
        pdsDataServiceId: id,
        namespace: `${env?.domainId}`
      },
      callback: data => {
        getDirTreeData(data.pdsDataServiceCatalogId||'', data.offset);
      },
      error: () => {
        setLoading(false);
        getDirTreeData();
      }
    });
  }

  const getDirTreeData = (defaultSelectedId='', offset=null, type='refresh') => {

    setLoading(true);
    dispatch({
      type: (type==='refresh')?'pds.refreshCatalog':'pds.loadDataServiceCatalog',
      callback: data => {

        data.key = data.id||'';
        data.title = data.name||'';
        data.children = data.subCatalogs||[];

        let defaultItem = null;

        function recursion(subCatalogs) {

          if ((subCatalogs||[]).length===0) return;

          (subCatalogs||[]).forEach(catalog=> {
            catalog.key = catalog.id||'';
            catalog.title = catalog.name||'';
            catalog.children = catalog.subCatalogs||[];

            if (catalog.id === defaultSelectedId) {
              defaultItem = catalog;
            }

            recursion(catalog.subCatalogs);
          })
        } 

        recursion(data.subCatalogs);
        setLoading(false);
        setTreeData(data.subCatalogs||[]);
        setRootId(data.id||'');

        const _dataList = [];
        generateList(data.subCatalogs||[], _dataList);
        setDataList(_dataList);

        if (defaultItem) {
          const expandedKeys = _dataList
            .map(item => {
              if (item.key.indexOf(defaultSelectedId) > -1) {
                return getParentKey(item.key, data.subCatalogs||[]);
              }
              return null;
            })
            .filter((item, i, self) => item && self.indexOf(item) === i);

          setExpandedKeys([...expandedKeys, defaultSelectedId]);
          setAutoExpandParent(true);

          setItem(defaultItem);
          onSelect && onSelect(defaultItem.key||'', offset);
        
        } else if (refrence === '') {
          
          const currentItem = (data.subCatalogs||[]).length>0?data.subCatalogs[0]: null;

          setItem(currentItem);
          if (currentItem && currentItem.key) {
            setExpandedKeys([currentItem?.key]);
          }

          onSelect && onSelect(currentItem?(currentItem.key||''):'');
          
        }
      },
      error: () => {
        setLoading(false);
      }
    })
  }

  const getStateTreeData = () => {
    setLoading(true);
    dispatch({
      type: 'pds.loadStateCatalog',
      payload: {
        isOnlyEnding
      },
      callback: data => {
        setLoading(false);
        let _treeData = data?.subCatalogs||[];
        _treeData.forEach(item => {
          item.title = item.cnName;
          item.key = item.id; 
        })

        setTreeData(_treeData);
        setItem(_treeData.length>0?_treeData[0]:{});
        onSelect && onSelect(_treeData.length>0?_treeData[0].key:'');
      },
      error: () => {
        setLoading(false);
      }
    });
  }

  const generateList = (treeData, list, path = null) => {
    for (let i = 0; i < treeData.length; i++) {
      const node = treeData[i];
      const { id, name } = node;

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

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

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

  const onViewClick = ({ key }) => {

    if (viewSelectedKey &&  viewSelectedKey===key ) return;

    setViewSelectedKey(key);
    setSearchKeyword('');
    onViewChange && onViewChange(key);

    if (key === 'dir') {
      getDirTreeData();
    } else {
      getStateTreeData();
    }
  }

  // const onSyncMenuClick = ({ key }) => {

  //   setDomainSelectedKey(key);
  //   dispatch({
  //     type: 'datamodel.setRootDomainId',
  //     payload: {
  //       params: {
  //         domainId: key
  //       }
  //     },
  //     callback: () => {
  //       setIsSetRootId(true);
  //       getDirTreeData('', null, 'load');
  //     }
  //   });

  // }

  const onTreeSelect = (keys,data) => {

    if ((keys||[]).length === 0) {
      return;
    }

    const _item = {...data.selectedNodes[0]||[]};

    setItem(_item);
    onSelect && onSelect(_item.key);
  }

  const add = () => {
    setVisible(true);
    setType('add');
  }

  const update = () => {
    setVisible(true);
    setType('update');
  }

  const refresh = () => {
    if (viewSelectedKey==='dir') {
      getDirTreeData(item?.key||'');
    } else {
      getStateTreeData(item?.key||'');
    }
  }

  const sync = () => {
    getDirTreeData(item?.key||'', null, 'load');
  }

  const moveNode = (steps) => {
    setLoading(true);
    dispatch({
      type: 'pds.upDownCatalog',
      payload: {
        pdsDataServiceCatalogId: currentRightClickDir.id,
        steps
      },
      callback: () => {
        showMessage('success', (steps===-1)?'上移目录成功':'下移目录成功');
        getDirTreeData(item.id);
      }, 
      error: () => {
        setLoading(false);
      }
    });
  }

  const deleteNode = () => {
    modal.confirm({
      title: '提示!',
      content: '删除目录会删除相关的服务,您确定删除吗?',
      onOk: () => {
        setLoading(true);
        dispatch({
          type: 'pds.deleteCatalog',
          payload: {
            params: {
              pdsDataServiceCatalogId: currentRightClickDir.id
            }
          },
          callback: () => {
            showMessage('success', '删除目录成功');

            if (item && currentRightClickDir && item.id===currentRightClickDir.id) {
              getDirTreeData();
            } else {
              getDirTreeData(item.id);
            }
          }, 
          error: () => {
            setLoading(false);
          }
        });
      }
    });

  }

  const onUpdateTreeItemModalOk = (id, updateItem) => {
    setVisible(false);
    getDirTreeData(id);
  }

  const onUpdateTreeItemModalCancel = () => {
    setVisible(false);
  }

  const treeDirectoryChanged = (did) => {
    let defaultItem = null;

    function recursion(subCatalogs) {

      if ((subCatalogs||[]).length===0) return;

      (subCatalogs||[]).forEach(catalog=> {
        catalog.key = catalog.id||'';
        catalog.title = catalog.name||'';
        catalog.children = catalog.subCatalogs||[];

        if (catalog.id === did) {
          defaultItem = catalog;
        }

        recursion(catalog.subCatalogs);
      })
    } 

    recursion(treeData||[]);

    if (defaultItem) {
      const expandedKeys = dataList
        .map(item => {
          if (item.key.indexOf(did) > -1) {
            return getParentKey(item.key, treeData||[]);
          }
          return null;
        })
        .filter((item, i, self) => item && self.indexOf(item) === i);

      setExpandedKeys([...expandedKeys, did]);
      setAutoExpandParent(true);

      setItem(defaultItem);
      onSelect && onSelect(defaultItem.key||'');
    
    }
  }

  const onAutoCompleteSearch = (searchText) => {
    setOptions(
      !searchText ? [] : (dataList||[]).filter(item => item.title.indexOf(searchText)!==-1),
    );
  };

  const onAutoCompleteChange = (value) => {
    setSearchKeyword(value);
  }

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

  const displayMenu = (e) => {
    show(e);
  }

  const exportMenu = (
    <Menu selectedKeys={[viewSelectedKey]} onClick={onViewClick}>
    {
      viewModes && viewModes.map(item => {
        return (
          <Menu.Item key={item.key} value={item.key} >
            <div style={{ textAlign: 'center' }}>
            {item.name}
            </div>
          </Menu.Item>
        )
      })
    }
    </Menu>
  );

  // const syncMenu = (
  //   <Menu selectedKeys={[domainSelectedKey]} onClick={onSyncMenuClick}>
  //   {
  //     domains && domains.map(domain => {
  //       return (
  //         <Menu.Item key={domain.domainId} value={domain.domainId} >{domain.domainName}</Menu.Item>
  //       )
  //     })
  //   }
  //   </Menu>
  // );

  const classes = classnames('model-tree', {
    'model-tree-recatalog': (refrence === 'recatalog')
  });  

  return (
    <div className={classes}>
    {
      (refrence==='') && <div
        className='p-3'
        style={{
          display: 'flex',
          borderBottom: "1px solid #EFEFEF",
          height: 57,
          alignItems: 'center',
          // justifyContent: (viewSelectedKey==='dir' && getDataModelerRole(user)===DataModelerRoleAdmin)?'space-between':'',
        }}
      >
        <Dropdown overlay={exportMenu} placement="bottomLeft">
          <Tooltip title="视角">
            <UnorderedListOutlined className='default' style={{ fontSize:16,cursor:'pointer' }} />
          </Tooltip>
        </Dropdown>

        {
          // (viewSelectedKey==='dir' && getDataModelerRole(user)===DataModelerRoleAdmin && !isOnlyEnding) && ( 
          //   <Tooltip title="新增目录" className='ml-6'>
          //     <PlusOutlined className='default' onClick={add} style={{ fontSize:16,cursor:'pointer' }} />
          //   </Tooltip>
          // )
        }     
        {/* {
          (viewSelectedKey==='dir' && getDataModelerRole(user)===DataModelerRoleAdmin) && ( 
            <Tooltip title="存量模型导入" className='ml-2'>
              <ImportOutlined className='default' onClick={() => { importStockModel && importStockModel() }} style={{ fontSize:16,cursor:'pointer' }} />
            </Tooltip>
          )
        } */}

        <Tooltip title="刷新目录" className='ml-6'>
          <Button type='text' icon={<ReloadOutlined className='default' />} size='small' onClick={refresh} />
        </Tooltip>

        {/* {
          (viewSelectedKey==='dir' && getDataModelerRole(user)===DataModelerRoleAdmin) && !isSetRootId && (
            <Dropdown overlay={syncMenu} placement="bottomLeft"> 
              <Tooltip title="同步目录">
                <SwapOutlined className='default ml-2' style={{ fontSize:16,cursor:'pointer', transform: 'rotate(90deg)', }} />
              </Tooltip>
            </Dropdown>
          )
        }  */}

        {
          (viewSelectedKey==='dir') 
          // && getDataModelerRole(user)===DataModelerRoleAdmin) 
          // && isSetRootId 
          && (
              <Tooltip title="同步目录" className='ml-6'>
                <Button type='text' icon={<SwapOutlined className='default' style={{ transform: 'rotate(90deg)' }} />} size='small' onClick={sync} />
              </Tooltip>
          )
        }   
      </div>
    }
      <div className='p-3'>
        <Spin spinning={loading} >
          {
            (viewSelectedKey==='dir') && <AutoComplete
              allowClear
              value={searchKeyword}
              style={{ marginBottom: 10, width: '100%' }}
              placeholder='搜索目录'
              onSelect={onAutoCompleteSelect}
              onSearch={onAutoCompleteSearch}
              onChange={onAutoCompleteChange}
              onClear={() => { setSearchKeyword(''); }}
            >
            {
              (options||[]).map((item, index) => {
                return (
                  <Option key={item.key} value={item.value}>
                    <div style={{ whiteSpace: 'normal' }}>
                    {highlightSearchContentByTerms(item.title, [searchKeyword])}
                    </div>
                  </Option>
                );
              })
            }
            </AutoComplete>
          }
          <Tree 
            className='tree-contextmenu'
            onExpand={onExpand}
            expandedKeys={expandedKeys}
            autoExpandParent={autoExpandParent}
            showLine 
            showIcon={false} 
            onSelect={onTreeSelect} 
            treeData={treeData} 
            selectedKeys={[item?item.key:'']} 
            titleRender={(nodeData) => {
              return <span title={nodeData?.remark||''} className='cursor-pointer-contextmenu'>{(nodeData.status===-1)?`${nodeData?.name}_已下线`:nodeData?.name||''}</span>;
            }}
            onRightClick={({event, node}) => {
              if (viewSelectedKey==='dir') {
                setCurrentRightClickDir(node);
                displayMenu(event);
              }
            }}
          />      
        </Spin>
      </div>
      <UpdateTreeItemModal 
        visible={visible} 
        type={type}
        item={(type==='add')?item:currentRightClickDir}
        rootId={rootId}
        onOk={onUpdateTreeItemModalOk} 
        onCancel={onUpdateTreeItemModalCancel} 
        />
      {
        (refrence!=='recatalog') && <RcMenu id={MENU_ID}>
          <RcItem id="edit" onClick={update}>
            修改目录
          </RcItem>
          <RcItem id="up" onClick={() => { moveNode(-1); }}>
            上移目录
          </RcItem> 
          <RcItem id="down" onClick={() => { moveNode(1); }}>
            下移目录
          </RcItem> 
          <RcItem id="delete" onClick={deleteNode}>
            删除目录
          </RcItem>
        </RcMenu> 
      } 
      {contextHolder}  
    </div>
  );
}

export default ModelTree;