/*
 * @Author: yuananting
 * @Date: 2021-02-23 18:28:50
 * @LastEditors: wufan
 * @LastEditTime: 2021-07-23 15:03:50
 * @Description: 助学工具-课程分类
 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
 */
import React, { Component } from 'react';
import Breadcrumbs from '@/components/Breadcrumbs';
import './CourseCategoryManage.less';
import OpearteCourseCategoryModal from '../modal/OpearteCourseCategoryModal';
import AidToolService from '@/domains/aid-tool-domain/AidToolService';
import User from '@/common/js/user';
import { Tree, Input, Space, Button, Menu, Dropdown, message, Modal } from 'antd';
import ShowTips from '@/components/ShowTips';
import LottieIcon from '@/components/LottieIcon';
const { DirectoryTree } = Tree;
const { Search } = Input;
const { confirm } = Modal;

class CourseCategoryManage extends Component {
  constructor(props) {
    super(props);
    this.state = {
      operateCourseCategoryModal: null, //新增或编辑分类模态框
      treeData: [],
      originTreeData: [],
      treeMap: {},
      selectedKeys: ['null'],
      autoExpandParent: true,
    };
  }

  componentDidMount() {
    this.queryCategoryTree('init');
  }

  getWholeTree = () => {
    let query = {
      bizType: 'QUESTION',
      count: false,
      source: 0,
      userId: User.getStoreUserId(),
      tenantId: User.getStoreId(),
    };
    AidToolService.queryCategoryTree(query).then((res) => {
      const { categoryList = [] } = res.result;
      this.setState({ originTreeData: categoryList }, () => {
        let map = {};
        let topItem = [];
        categoryList.forEach((item) => {
          topItem.push(item);
        });
        this.setState({
          treeMap: Object.assign(this.getTreeMap(categoryList, map), {
            0: {
              sonCategoryList: topItem,
            },
          }),
        });
      });
    });
  };

  // 查询分类树
  queryCategoryTree = (operateType, categoryName) => {
    this.getWholeTree();
    this.setState({ categoryName });
    let query = {
      bizType: 'QUESTION',
      count: false,
      source: 0,
      categoryName,
      userId: User.getStoreUserId(),
      tenantId: User.getStoreId(),
    };
    AidToolService.queryCategoryTree(query).then((res) => {
      const { categoryList = [] } = res.result;
      let str = '未分类';
      if (categoryName) {
        this.setState({ autoExpandParent: true });
        if (str.indexOf(categoryName) < 0) {
          this.setState({
            treeData: this.renderTreeNodes(categoryList, categoryName),
          });
          let nodeId = [];
          Object.keys(this.state.treeMap).forEach((item) => {
            nodeId.push(item);
          });
          this.setState({ expandedKeys: nodeId });
        } else {
          const defaultNode = {
            id: 'null',
            categoryName: '未分类',
            categoryCount: 0,
            parentId: '0',
            categoryLevel: 0,
          };
          categoryList.unshift(defaultNode);
          this.setState({
            treeData: this.renderTreeNodes(categoryList, categoryName),
          });
          let nodeId = [];
          Object.keys(this.state.treeMap).forEach((item) => {
            nodeId.push(item);
          });
          if (operateType === 'init') {
            this.setState({ expandedKeys: nodeId });
          }
        }
      } else {
        this.setState({ autoExpandParent: false });
        const defaultNode = {
          id: 'null',
          categoryName: '未分类',
          categoryCount: 0,
          parentId: '0',
          categoryLevel: 0,
        };
        categoryList.unshift(defaultNode);
        this.setState({ treeData: this.renderTreeNodes(categoryList, categoryName) });
        if (operateType === 'init') {
          this.setState({ expandedKeys: [] });
        }
      }
    });
  };

  // 树节点渲染-内容处理
  renderTreeNodes = (data, value) => {
    let newTreeData = data.map((item) => {
      item.title = item.categoryName;
      item.key = item.id;
      item.title = (
        <div
          style={{
            opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
          }}
          className='node-title-div'
          onMouseOver={(e) => {
            let mouseNodeOpts = e.currentTarget.getElementsByTagName('div')[0];
            if (mouseNodeOpts) {
              mouseNodeOpts.style.visibility = 'visible';
            }
          }}
          onMouseOut={(e) => {
            let mouseNodeOpts = e.currentTarget.getElementsByTagName('div')[0];
            if (mouseNodeOpts) {
              mouseNodeOpts.style.visibility = 'hidden';
            }
          }}>
          <span>{item.categoryName}</span>
          {item.categoryName !== '未分类' && (
            <Space className='title-opts' size={16}>
              <span
                onClick={() => {
                  const { originTreeData } = this.state;
                  if (
                    (item.categoryLevel === 0 && originTreeData.length >= 29) ||
                    (item.categoryLevel > 0 && this.getRelatedNodes(item.parentId).length >= 30)
                  ) {
                    return message.info('最多只能添加30个分类');
                  }
                  this.newEditCourseCategory('newEqualLevelCategory', 'equal', 'new', item);
                }}>
                <span className='icon iconfont' style={{ color: '#BFBFBF' }}>
                  &#xe7f5;{' '}
                </span>
                <span>同级</span>
              </span>
              {item.categoryLevel < 4 && (
                <span
                  onClick={() => {
                    if (this.getRelatedNodes(item.id) && this.getRelatedNodes(item.id).length >= 30) {
                      message.info('最多只能添加30个子分类');
                      return;
                    }
                    this.newEditCourseCategory('newChildLevelCategory', 'child', 'new', item);
                  }}>
                  <span className='icon iconfont' style={{ color: '#BFBFBF' }}>
                    &#xe7f8;{' '}
                  </span>
                  <span>子级</span>
                </span>
              )}
              <Dropdown overlay={this.initDropMenu(item)}>
                <span>
                  <span className='icon iconfont' style={{ color: '#BFBFBF' }}>
                    &#xe7f7;{' '}
                  </span>
                  <span>更多</span>
                </span>
              </Dropdown>
            </Space>
          )}
        </div>
      );
      item.icon =
        item.categoryName === '未分类' ? (
          <img
            style={{
              width: '24px',
              height: '24px',
              opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
            }}
            src='https://image.xiaomaiketang.com/xm/defaultCategory.png'
            alt=''
          />
        ) : (
          <img
            style={{
              width: '24px',
              height: '24px',
              opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
            }}
            src='https://image.xiaomaiketang.com/xm/hasCategory.png'
            alt=''
          />
        );

      if (item.sonCategoryList) {
        item.children = this.renderTreeNodes(item.sonCategoryList, value);
      }
      return item;
    });
    return newTreeData;
  };

  // 树结构平铺
  getTreeMap = (data, map) => {
    data.forEach((item) => {
      map[item.id] = item;
      if (item.sonCategoryList && item.sonCategoryList.length > 0) {
        this.getTreeMap(item.sonCategoryList, map);
      }
    });

    return map;
  };

  // 新增或编辑分类
  newEditCourseCategory = (categoryType, addLevelType, type, node) => {
    let title = '';
    let label = '';
    switch (categoryType) {
      case 'newEqualLevelCategory':
        title = '新增分类';
        label = '分类名称';
        break;
      case 'newChildLevelCategory':
        title = '新增子分类';
        label = '子分类名称';
        break;
      case 'editEqualLevelCategory':
        title = '编辑分类';
        label = '分类名称';
        break;
      case 'editChildLevelCategory':
        title = '编辑子分类';
        label = '子分类名称';
        break;
    }
    const m = (
      <OpearteCourseCategoryModal
        node={node}
        addLevelType={addLevelType}
        type={type}
        title={title}
        label={label}
        close={() => {
          this.queryCategoryTree('remain', this.state.categoryName);
          this.setState({
            operateCourseCategoryModal: null,
          });
        }}
      />
    );
    this.setState({ operateCourseCategoryModal: m });
  };

  // 删除分类
  delCategory = (item) => {
    return confirm({
      title: '确认删除该分类吗？',
      content: '删除后，分类下的所有内容将自动转入“未分类”中。',
      icon: <span className='icon iconfont default-confirm-icon'>&#xe839; </span>,
      okText: '删除',
      okType: 'danger',
      cancelText: '取消',
      onOk: () => {
        let params = {
          categoryId: item.id,
          source: 0,
          tenantId: User.getStoreId(),
          userId: User.getStoreUserId(),
        };
        AidToolService.delCategory(params).then((res) => {
          if (res.success) {
            message.success('删除分类成功');
            this.queryCategoryTree('remain', this.state.categoryName);
          }
        });
      },
    });
  };

  // 更多操作-【重命名 删除】
  initDropMenu = (item) => {
    return (
      <Menu>
        <Menu.Item key='0'>
          <span
            onClick={() => {
              let categoryType = item.categoryLevel === 0 ? 'editEqualLevelCategory' : 'editChildLevelCategory';
              this.newEditCourseCategory(categoryType, 'equal', 'edit', item);
            }}>
            重命名
          </span>
        </Menu.Item>
        <Menu.Item key='1'>
          <span
            onClick={() => {
              this.delCategory(item);
            }}>
            删除
          </span>
        </Menu.Item>
      </Menu>
    );
  };

  // 获取相关节点
  getRelatedNodes = (parentId) => {
    return this.state.treeMap[parentId] ? this.state.treeMap[parentId].sonCategoryList : [];
  };

  // 获取拖拽目标父节点层级
  getParentDragNodesLevel = (dragNode) => {
    if (!dragNode) {
      return [];
    }
    let dragNodes = [];
    dragNodes.push(dragNode.id);

    if (dragNode.parentId !== '0') {
      dragNodes = dragNodes.concat(this.getParentDragNodesLevel(this.state.treeMap[dragNode.parentId]));
    }
    return dragNodes;
  };

  // 获取拖拽节点层级
  getDragNodesLevel = (dragNode) => {
    let dragNodes = [];
    if (dragNode.sonCategoryList && dragNode.sonCategoryList.length > 0) {
      dragNode.sonCategoryList.forEach((item) => {
        dragNodes.push(item.categoryLevel);
        if (item.sonCategoryList && item.sonCategoryList.length > 0) {
          dragNodes = dragNodes.concat(this.getDragNodesLevel(item));
        }
      });
    }
    return [...new Set(dragNodes)];
  };

  // 拖拽
  onDrop = (info) => {
    // 带搜索时的分类树不允许拖拽
    // 不允许其他节点拖拽到未分类中
    // 不允许其他节点拖拽到未分类之前
    if (
      this.state.categoryName ||
      (info.node.categoryName === '未分类' && info.dropPosition === 0) ||
      (info.node.categoryName === '未分类' && info.dropToGap && info.dropPosition === -1)
    ) {
      return;
    }
    // 未分类不可以拖拽
    if (info.dragNode.categoryName === '未分类' && info.dragNode.categoryLevel === 0) return message.info('“未分类”为默认分类暂不支持移动');

    let targetParentId = info.dropToGap ? info.node.parentId : info.node.id;
    let relatedNodes = this.getRelatedNodes(targetParentId);
    if (!((info.dropToGap && info.node.parentId === info.dragNode.parentId) || (!info.dropToGap && info.node.id === info.dragNode.parentId))) {
      if (this.state.treeMap[targetParentId].categoryLevel >= 4) {
        return message.info('最多支持5级分类');
      } else {
        let nodesArr = this.getDragNodesLevel(this.state.treeMap[info.dragNode.id]);
        let parentArr = this.getParentDragNodesLevel(this.state.treeMap[targetParentId]);
        if (nodesArr.length + parentArr.length > 4) {
          return message.info('最多支持5级分类');
        }
      }
      if (relatedNodes && relatedNodes.length >= 30) {
        return message.info('最多只能添加30个分类');
      }
    }
    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 loop = (data, key, callback) => {
      for (let i = 0; i < data.length; i++) {
        if (data[i].key === key) {
          return callback(data[i], i, data);
        }
        if (data[i].sonCategoryList) {
          loop(data[i].sonCategoryList, key, callback);
        }
      }
    };
    const data = [...this.state.treeData];

    let getSuf = function (name, originCategoryName, sufIndex) {
      if (relatedNodes && relatedNodes.length > 0) {
        let sameNameNodes = [];
        relatedNodes.forEach((item) => {
          if (item.id === info.dragNode.id) return true;
          if (item.categoryName === name) {
            sameNameNodes.push(item);
          }
        });
        if (sameNameNodes.length > 0) {
          sufIndex++;
          return getSuf(originCategoryName + `(${sufIndex})`, originCategoryName, sufIndex);
        }
      }
      return sufIndex;
    };

    let dragObj;
    loop(data, dragKey, (item, index, arr) => {
      arr.splice(index, 1);
      item.parentId = targetParentId;
      if (item.originCategoryName) {
        item.categoryName = item.originCategoryName;
      } else {
        item.originCategoryName = item.categoryName;
      }
      info.dragNode.categoryName = item.originCategoryName;
      let sufIndex = getSuf(info.dragNode.categoryName, item.originCategoryName, 0);
      item.categoryName = item.categoryName + (sufIndex ? `(${sufIndex})` : '');
      item.categoryName = item.originCategoryName + (sufIndex ? `(${sufIndex})` : '');
      dragObj = item;
    });

    if (!info.dropToGap) {
      loop(data, dropKey, (item) => {
        item.sonCategoryList = item.sonCategoryList || [];
        item.sonCategoryList.unshift(dragObj);
      });
    } else if ((info.node.props.sonCategoryList || []).length > 0 && info.node.props.expanded && dropPosition === 1) {
      loop(data, dropKey, (item) => {
        item.sonCategoryList = item.children || [];
        item.sonCategoryList.unshift(dragObj);
      });
    } else {
      let ar;
      let i;
      loop(data, dropKey, (item, index, arr) => {
        ar = arr;
        i = index;
      });
      if (dropPosition === -1) {
        ar.splice(i, 0, dragObj);
      } else {
        ar.splice(i + 1, 0, dragObj);
      }
    }
    data.shift();
    let newTreeData = this.renderTreeNodes(this.handleLoop(data, 0));
    this.setState({ treeData: newTreeData });
    let firstParentNode = {
      categoryCount: 0,
      categoryLevel: 0,
      categoryName: '',
      id: 0,
      parentId: 0,
      parentName: '',
      rootId: 0,
      sonCategoryList: [...newTreeData],
      sort: 0,
      source: 0,
      tenantId: User.getStoreId(),
      userId: User.getStoreUserId(),
    };
    let movedCategory = this.movedNodeFind(newTreeData, info.dragNode.id);
    let parentCategory = movedCategory.parentId === '0' ? firstParentNode : this.movedNodeFind(newTreeData, targetParentId);
    let params = {
      movedCategory,
      parentCategory,
      source: 0,
      tenantId: User.getStoreId(),
      userId: User.getStoreUserId(),
    };

    AidToolService.moveCategory(params).then((res) => {
      this.queryCategoryTree('remain');
    });
  };

  // 获取移动节点信息
  movedNodeFind(categoryList, movedId) {
    for (const item of categoryList) {
      if (item.id === movedId) return item;
      if (item.sonCategoryList && item.sonCategoryList.length > 0) {
        const node = this.movedNodeFind(item.sonCategoryList, movedId);
        if (node) return node;
      }
    }
    return null;
  }

  handleLoop = (data, level) => {
    data.map((item, index) => {
      item.sort = index;
      item.categoryLevel = level;
      if (item.sonCategoryList) {
        item.children = this.handleLoop(item.sonCategoryList, level + 1);
        item.sonCategoryList = this.handleLoop(item.sonCategoryList, level + 1);
      }
      return item;
    });
    return data;
  };

  // 树状展开事件
  onExpand = (expandedKeys) => {
    this.setState({ expandedKeys });
  };

  // 树状选中事件
  onSelect = (selectedKeys) => {
    this.setState({ selectedKeys });
  };

  render() {
    const { treeData, originTreeData, expandedKeys, selectedKeys, autoExpandParent, operateCourseCategoryModal } = this.state;
    return (
      <div className='page course-category-manage'>
        {['aid', 'knowledge'].includes(getParameterByName('from')) ? (
          <Breadcrumbs navList='分类管理' goBack={() => window.RCHistory.goBack()} />
        ) : (
          <div className='content-header'>分类管理</div>
        )}
        <div className='box'>
          <div className='search-condition'>
            <span className='search-label'>搜索名称：</span>
            <Search
              placeholder='搜索分类名称'
              style={{ width: '300px' }}
              onSearch={(value) => this.queryCategoryTree('init', value)}
              className='search-input'
              enterButton={<span className='icon iconfont'>&#xe832;</span>}
            />
          </div>
          <Button
            type='primary'
            onClick={() => {
              if (originTreeData.length >= 29) {
                message.info('最多只能添加30个分类');
                return;
              }
              this.newEditCourseCategory('newEqualLevelCategory', 'equal', 'new');
            }}>
            新增一级分类
          </Button>
          <div className='show-tips' style={{ marginTop: '12px', width: '900px' }}>
            <ShowTips message='为方便管理，该分类用于课程、题库、知识库等模块，改动将同步各模块更新' />
          </div>
          <div className='course-category-tree'>
            {
              <Choose>
                <When condition={treeData.length !== 0}>
                  <DirectoryTree
                    expandedKeys={expandedKeys}
                    autoExpandParent={autoExpandParent}
                    onExpand={this.onExpand}
                    selectedKeys={selectedKeys}
                    onSelect={this.onSelect}
                    draggable
                    blockNode
                    onDrop={this.onDrop}
                    treeData={treeData}></DirectoryTree>
                </When>
                <Otherwise>
                  <LottieIcon title={<span className='desc'>搜索无结果</span>} type='search' size={150} />
                </Otherwise>
              </Choose>
            }
          </div>
        </div>
        {operateCourseCategoryModal}
      </div>
    );
  }
}

export default CourseCategoryManage;
