package io.renren.modules.levelManage.controller;

import cn.hutool.core.collection.CollectionUtil;
import io.renren.common.utils.R;
import io.renren.common.utils.RandomGen;
import io.renren.common.utils.SubString;
import io.renren.common.utils.ToEnglish;
import io.renren.modules.levelManage.entity.LevelEntity;
import io.renren.modules.levelManage.entity.LevelRelationEntity;
import io.renren.modules.levelManage.entity.UniversalTableEntity;
import io.renren.modules.levelManage.service.*;
import io.renren.modules.sys.controller.AbstractController;
import lgh.springboot.starter.hbase.template.HBaseTemplate;
import org.apache.hadoop.hbase.io.compress.Compression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 *
 *
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2022-03-30 16:57:16
 */
@RestController
@RequestMapping("/universaltable")
public class UniversalTableController extends AbstractController {

    @Autowired
    private UniversalTableService universalTableService;
    @Autowired
    private LevelService levelService;
    @Autowired
    private LevelTableService levelTableService;
    @Autowired
    private LevelRelationService levelRelationService;
    @Autowired
    private HBaseTemplate hBaseTemplate;
    @Autowired
    private ProjectAttributesService projectAttributesService;
    /**
     * 列表
     */
    @RequestMapping("/list")
    public R list(@RequestParam("tableId") Long tableId,@RequestParam("page") Integer page,@RequestParam("size") Integer size)
    {
        LevelEntity levelEntity = levelService.getById(tableId);
        String tableName = levelEntity.getTableName();
        List<String> tableCols = levelTableService.listColsByLevelId(tableId);
        List<Map<String,Object>> data=universalTableService.list(tableName,tableCols,page,size);
        //data是<列名，具体值>的list

        //对bool值需要修改为是/否，否则前端不显示（应该在前端解决，但是做不到，先在后端进行）
        //先获取所有是bool的列，通过遍历list，用列名对所有value修改
        List<String> boolCols=levelTableService.listBoolColsById(tableId);

        for(Map<String,Object> map :data)
        {
            for(String col: boolCols)
            {
                if((boolean) map.get(col))
                {
                    map.put(col,"是");
                }
                else
                    map.put(col,"否");
            }
        }
        SubString.subStringList(data);
        Integer count=universalTableService.getCount(tableName);
        return R.ok().put("data",data).put("count",count);
    }

    /**
     * 根据父层级具体内容的id进行查询
     */
    @RequestMapping("/listWithParentRowId")
    public R listWithParentRowId(@RequestParam("parentTableId") Long parentTableId,@RequestParam("parentRowId") Long parentRowId,
            @RequestParam("tableId") Long tableId,@RequestParam("page") Integer page,@RequestParam("size") Integer size)
    {
        //通过id拿表名，方便使用
        LevelEntity levelEntity = levelService.getById(tableId);
        String tableName = levelEntity.getTableName();
        //获取表的字段，一会传数据回去的时候需要列的信息
        List<String> tableCols = levelTableService.listColsByLevelId(tableId);

        //原先的逻辑是通过父表id和父表行id，锁定子表id和子表行id，通过对子表id进行匹配，搜索出子表行
        //现在优化了逻辑，因为子表只有一个父表，因此只需要子表行和父表id，就可以锁定子表行
        List<LevelRelationEntity> relations= levelRelationService.selectByParentRowAndSonTable(tableId,parentRowId);
        //将所有应获取的子表行id写入ids
        List<Long> ids = new ArrayList<>();
        for(LevelRelationEntity relation: relations)
        {
            ids.add(relation.getSonRowId());
        }
        if(ids.size()==0)
        {
            return R.ok().put("count",0);
        }

        //通过ids和页面个数限制，查找所有的值
        List<Map<String,Object>> data=universalTableService.listBySonIds(tableName,tableCols,ids,page,size);

        //对bool值需要修改为是/否，否则前端不显示
        //先获取表中类型为bool的列，然后遍历data的值，将bool列的value修改为是/否
        List<String> boolCols=levelTableService.listBoolColsById(tableId);

        for(Map<String,Object> map :data)
        {
            for(String col: boolCols)
            {
                if((boolean) map.get(col))
                {
                    map.put(col,"是");
                }
                else
                    map.put(col,"否");
            }
        }
        SubString.subStringList(data);
        //总计个数就是ids的个数
        Integer count=ids.size();
        return R.ok().put("data",data).put("count",count);
    }

    /**
     * 获取信息，包括表名和表内内容
     */
    @RequestMapping("/selectById")
    public R list(@RequestParam("id") Long id,@RequestParam("tableId") Long tableId)
    {
        LevelEntity levelEntity = levelService.getById(tableId);
        String tableName = levelEntity.getTableName();
        List<String> tableCols = levelTableService.listColsByLevelId(tableId);
        Map<String,Object> data=universalTableService.selectById(id,tableName,tableCols);
        return R.ok().put("data",data);
    }

    /**
     * 获取字段信息
     */
    @RequestMapping("/getCols")
    public R getCols(@RequestParam("tableId") Long id)
    {
        //因为实际上给的应该是 字段名、中文名、类型
//        List<String> cols = levelTableService.listColsByLevelId(id);
//        List<String> comment = levelTableService.listCommentByLevelId(id);
//        List<String> type =levelTableService.listTypeByLevelId(id);
        //刚好有之前写的
        List<Map<String,Object>> data=levelTableService.listByLevelId(id);
        //不能直接map，会丢失顺序

        //先获取parentLevel，然后获取parentLevel的item作为新增时选择的候选值
        LevelEntity nowLevel=levelService.getById(id);
        Long parentId=nowLevel.getParentId();

        List<Map<String,Object>> parentItem=levelTableService.listByLevelId(parentId);
        return R.ok().put("data",data).put("parentItem",parentItem);
    }

    /**
     * 获取字段具体信息，用于修改，是selectById的变形
     */
    @RequestMapping("/getInfo")
    public R getInfo(@RequestParam("tableId") Long tableId,@RequestParam("rowId") Long id)
    {
        //获取列，list里面的Map的key为 name,remark,type
        List<Map<String,Object>> data=levelTableService.listByLevelId(tableId);
        //在list里面的Map添加新的key，值为value
        //先获取所有的值
        LevelEntity levelEntity = levelService.getById(tableId);
        String tableName = levelEntity.getTableName();
        List<String> tableCols = levelTableService.listColsByLevelId(tableId);
        Map<String,Object> valueMap=universalTableService.selectById(id,tableName,tableCols);
        //在list里面添加上面map的值，存到key为value的对里面
        for (Map<String,Object> item : data)
        {
            item.put("value", String.valueOf(valueMap.get(item.get("name"))));
        }

        SubString.subStringRow(data);
        return R.ok().put("data",data);
    }

    /**
     * 用于识别是否为特殊层级
     * @param id
     * @return
     */
    @RequestMapping("/hasHbaseTable")
    public R hasHbaseTable(@RequestParam("tableId") Long id)
    {
        LevelEntity levelEntity= levelService.getById(id);
        return R.ok().put("data",levelEntity.getHasHbasetable());
    }

    /**
     * 搜索
     */
    @RequestMapping("/selectByName")
    public R selectByName(@RequestParam("page") Integer page,@RequestParam("limit") Integer limit,
                          @RequestParam("tableId") Long id,@RequestParam("name") String name)
    {
        //获取查询需要的参数
        LevelEntity levelEntity = levelService.getById(id);
        String tableName = levelEntity.getTableName();
        List<String> tableCols = levelTableService.listColsByLevelId(id);

        List<Map<String,Object>> data=universalTableService.selectByName(tableName,tableCols,page,limit,name);
        SubString.subStringList(data);
        Integer count = universalTableService.getCountByName(tableName,name);
        return R.ok().put("data",data).put("count",count);
    }

    @RequestMapping("/selectByNameWithParent")
    public R selectByNameWithParent(@RequestParam("page") Integer page,@RequestParam("limit") Integer limit,
                          @RequestParam("tableId") Long id,@RequestParam("name") String name,
                          @RequestParam("parentRowId") Long parentRowId)
    {
        //获取查询需要的参数
        LevelEntity levelEntity = levelService.getById(id);
        String tableName = levelEntity.getTableName();
        List<String> tableCols = levelTableService.listColsByLevelId(id);
        List<Map<String,Object>> data=universalTableService.selectByNameWithParent(tableName,tableCols,page,limit,name,parentRowId,id);
        SubString.subStringList(data);
        Integer count = universalTableService.getCountByNameWithParent(tableName,name,parentRowId,id);
        return R.ok().put("data",data).put("count",count);
    }

//    @RequestMapping("/info/{id}")
//    public R info(@PathVariable("id") Long id){
//        LevelTableEntity levelTable = levelTableService.getById(id);
//
//        return R.ok().put("levelTable", levelTable);
//    }
//
    /**
     * 保存/新增
     */
    @RequestMapping("/save")
    public R save(@RequestBody Map<String,Object> map) throws ParseException{
        //先抽取属性，形成表结构，然后存进表里，最后返回ok
        //真正需要的字段
        List<Map<String,Object>> trueCols= new ArrayList<>();

        //获取的数据，需要进行处理
        List<Map<String,Object>> cols= (List<Map<String, Object>>) map.get("cols");
        Long uid=getUserId();
        Long tableId=Long.valueOf(map.get("tableId").toString());
        LevelEntity levelEntity = levelService.getById(tableId);
        String tableName = levelEntity.getTableName();
        Long parentTableId=0L;
        if(map.containsKey("parentTableId") && !map.get("parentTableId").toString().equals("undefined"))
        {
            parentTableId=Long.valueOf(map.get("parentTableId").toString());
        }
        Long parentRowId=0L;
        if(map.containsKey("parentRowId") && !map.get("parentRowId").toString().equals("undefined"))
        {
            parentRowId=Long.valueOf(map.get("parentRowId").toString());
        }

        //save没有字段id
        //先创建一个universalTable作为缓冲
        UniversalTableEntity universalTable=new UniversalTableEntity();
        universalTable.setCreateUser(uid);
        universalTable.setCreateDate(new Date());
        //对cols进行处理，去除没有value的字段，将特定字段：create_user进行修改
        for(Map<String,Object> col :cols)
        {
            if(col.get("cols").equals("name"))
            {
                universalTable.setName(RandomGen.formatName(col.get("value").toString()));
                col.put("value",universalTable.getName() );
            }
            else if(col.get("cols").equals("create_user"))
            {
                col.put("value",universalTable.getCreateUser());
            }
            else if(col.get("cols").equals("create_time"))
            {
                col.put("value",universalTable.getCreateDate());
            }
            else if (col.get("cols").equals("id"))
            {
                continue;
            }
            else if(col.get("cols").equals("hbaseTableName"))
            {
                //占位用，因为如果有hbaseTableName，必须有值，不然不能插入表中，这里插入的值后续需要被改掉，理论上没有用，但是还是先写整齐一些
                col.put("value","level_"+ToEnglish.getPinYin(universalTable.getName())+"_"+tableId+"_"+universalTable.getId());
            }
            else if(col.get("type").equals("date"))
            {
                String  str= col.get("value").toString();
                DateFormat format=new SimpleDateFormat("yyyy-MM-dd");
                Date date=format.parse(str);
                col.put("value",date);
            }
            trueCols.add(col);
        }
        //不可以直接通过map进行存储，需要通过类型接受一下，因为类型接受可以获取id,同时，需要将动态列作为参数传入，在map里面进行动态插入
        Long insert =universalTableService.saveWithCols(tableName,trueCols,universalTable);

        //进行关联表的存储
        //如果是第一层级的表，关系表里面不需要进行插入
        //如果不是第一层级的表，获取其parentTableId和parentRowId，进行插入
        if(parentTableId!=0)
        {
            LevelRelationEntity relationEntity=new LevelRelationEntity();
            relationEntity.setParentTableId(parentTableId);
            relationEntity.setParentRowId(parentRowId);
            relationEntity.setSonTableId(tableId);
            relationEntity.setSonRowId(universalTable.getId());
            if(!levelRelationService.save(relationEntity))
            {
                R.error().put("msg","表间关系存储失败");
            }
        }

        //进行hbase表的创建
        if(levelEntity.getHasHbasetable()==1)
        {
            List<String> info=new ArrayList<>();
            info.add("data");
            Compression.Algorithm algorithm = Compression.Algorithm.NONE;
            hBaseTemplate.createTable(("level_"+ToEnglish.getPinYin(universalTable.getName())+"_"+tableId+"_"+universalTable.getId()),info,algorithm);
            //关于hbaseName---level_用户输入的name_tableId_当前项插入表之后的id
            //但是插入的项中就有hbaseTableName
            //所以应该先插入项，然后获取了该项的id，再更新项
            if(!universalTableService.updateHbaseTableName(tableName, universalTable.getId(),
                "level_"+ToEnglish.getPinYin(universalTable.getName())+"_"+tableId+"_"+universalTable.getId()))
            {
                return R.error().put("msg","hbase信息更新失败");
            }
        }


        return R.ok();
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    public R update(@RequestBody Map<String,Object> map) throws ParseException{

        //先抽取属性，形成表结构，然后存进表里，最后返回ok
        //真正需要的字段
        List<Map<String,Object>> trueCols= new ArrayList<>();

        //获取的数据，需要进行处理
        List<Map<String,Object>> cols= (List<Map<String, Object>>) map.get("cols");
        Long id=Long.valueOf(map.get("id").toString());
        Long uid=getUserId();
        Long tableId=Long.valueOf(map.get("tableId").toString());
        LevelEntity levelEntity = levelService.getById(tableId);
        String tableName = levelEntity.getTableName();
        String orginRowName = universalTableService.selectNameById(tableName,id);

        Long parentTableId=0L;
        if(map.containsKey("parentTableId") && !map.get("parentTableId").toString().equals("undefined"))
        {
            parentTableId=Long.valueOf(map.get("parentTableId").toString());
        }
        Long parentRowId=0L;
        if(map.containsKey("parentRowId") && !map.get("parentRowId").toString().equals("undefined"))
        {
            parentRowId=Long.valueOf(map.get("parentRowId").toString());
        }
        //和save不同，update有字段id,但是实际上cols中不需要id，id需要作为另外的参数传入
        //先创建一个universalTable作为缓冲
        UniversalTableEntity universalTable=new UniversalTableEntity();
        universalTable.setCreateUser(uid);
        universalTable.setCreateDate(new Date());
        //对cols进行处理，去除没有value的字段，将特定字段进行修改
        for(Map<String,Object> col :cols)
        {
            if(col.get("cols").equals("name"))
            {
                //cols中的name是处理过的name，因此不需要再次substring
                if(col.get("value").toString().equals(orginRowName.substring(4)))
                {
                    universalTable.setName(orginRowName);
                    col.put("value",universalTable.getName());
                }
                else{
                    universalTable.setName(RandomGen.formatName(col.get("value").toString()));
                    col.put("value",universalTable.getName() );
                }

            }
            else if(col.get("cols").equals("create_user"))
            {
                col.put("value",universalTable.getCreateUser());
            }
            else if(col.get("cols").equals("create_time"))
            {
                col.put("value",universalTable.getCreateDate());
            }
            else if (col.get("cols").equals("id"))
            {
                continue;
            }
            else if(col.get("cols").equals("hbaseTableName"))
            {
                //这个hbaseTableName不能变，直接跳过
                continue;
            }
            else if(col.get("type").equals("date"))
            {
                String  str= col.get("value").toString();
                DateFormat format=new SimpleDateFormat("yyyy-MM-dd");
                Date date=format.parse(str);
                col.put("value",date);
            }
            trueCols.add(col);
        }
        //直接存储不可以，因为还是需要进行类的变化,因此需要将动态列作为参数传入，在map里面进行动态插入
        //因为dao里面不一样，所以不能直接用save
        universalTableService.updateWithCols(tableName,trueCols,id);

        //进行关联表的存储
        //关联中，本身是不能改变的，但是parent层级可以修改
        if(parentTableId!=0)
        {
            LevelRelationEntity relationEntity=levelRelationService.selectBySon(tableId,id);
            relationEntity.setParentTableId(parentTableId);
            relationEntity.setParentRowId(parentRowId);
            if(!levelRelationService.updateById(relationEntity))
            {
                R.error().put("msg","表间关系存储失败");
            }
        }
        //hbase的也不进行修改
        return R.ok();
    }
//
    /**
     * 删除
     */
    @RequestMapping("/delete")
    public R delete(@RequestParam("tableId") Long id,@RequestBody Long[] ids){

        LevelEntity tableName = levelService.getById(id);
        universalTableService.removeByIdsFromTableName(Arrays.asList(ids),tableName.getTableName());
        levelRelationService.deleteBySonTidRids(id,Arrays.asList(ids));
        return R.ok();
    }

    @RequestMapping("/listAllItem")
    public R listAllItem(@RequestParam("id") Long id)
    {
        LevelEntity levelEntity=levelService.getById(id);
        List<Map<String,Object>> items= universalTableService.listAllItem(levelEntity.getTableName());
        return R.ok().put("data",items);
    }

    @RequestMapping("/listNotLeafItem")
    public R listNotLeafItem(@RequestParam("id") Long id)
    {
        LevelEntity levelEntity=levelService.getById(id);
        List<Map<String,Object>> items= universalTableService.listNotLeafItem(levelEntity.getTableName());
        return R.ok().put("data",items);
    }

    /**
     * 用于显示第二层级的所有信息，与list的差别在于没有页面控制以及没有替换truefalse为是否
     * @param id    project的id
     * @return
     */
    @RequestMapping("/getRootAllItem")
    public R getRootAllItem(@RequestParam("id") Long id)
    {
        if(projectAttributesService.countProjectLevel(id).equals("0"))
            return R.ok("该项目未绑定层级!\n");
        Integer tableId=projectAttributesService.selectRootLevel(id);
        LevelEntity levelEntity=levelService.getById(tableId);
        List<String> tableCols = levelTableService.listColsByLevelId(levelEntity.getId());
        List<Map<String,Object>> items= universalTableService.listAllItemInfo(levelEntity.getTableName(),tableCols);
        //data是<列名，具体值>的list
        //应该不需要将true/false替换是否
        //去除名字前面的随机数
        SubString.subStringList(items);
        return R.ok().put("data",items).put("levelId",tableId);
    }

    /**
     * 用于显示第二层级的所有信息，与list的差别在于没有页面控制以及没有替换truefalse为是否
     * @param id    project的id
     * @param page  分页信息
     * @param size  分页信息
     * @return
     */
    @RequestMapping("/getRootAllItemWithLimit")
    public R getRootAllItemWithLimit(@RequestParam("id") Long id,@RequestParam("page") Integer page,@RequestParam("size") Integer size)
    {
        if(projectAttributesService.countProjectLevel(id).equals("0"))
            return R.ok("该项目未绑定层级!\n");
        Integer tableId=projectAttributesService.selectRootLevel(id);
        LevelEntity levelEntity=levelService.getById(tableId);
        List<String> tableCols = levelTableService.listColsByLevelId(levelEntity.getId());
        List<Map<String,Object>> items= universalTableService.listAllItemInfo(levelEntity.getTableName(),tableCols);
        //data是<列名，具体值>的list
        //应该不需要将true/false替换是否
        //去除名字前面的随机数
        SubString.subStringList(items);
        //分页筛选
        page=(page-1)*size;
        List<Map<String,Object>> subData= CollectionUtil.sub(items,page,page+size);
        return R.ok().put("data",subData).put("levelId",tableId).put("count",items.size());
    }

    /**
     * 获取第二层级的页面左侧的信息，取所有属性
     * 应当在用户点击了第一层级的具体item后进行
     * @param id    project的id
     * @return
     */
    @RequestMapping(value={"/getRootLevel","/getRootLeafNotItem"})
    public R getRootLeafNotItem(@RequestParam Long id){
        //1.获取所有parent_id=0,并且project_id为所选id,并且enabled=1的level，应该只有一个
        List<LevelEntity> candidateLevel=levelService.getRootLevel(id);
        LevelEntity level=candidateLevel.get(0);
        //2.获取该level的表，并且从该表中查询所有数据
        //因为最后一层（测点）是不可操作的，我们可选的是倒数第二层，因此这里不应该展示任何叶子节点
        String tableName=level.getTableName();
        //为了显示所有信息，这里需要获取列字段
        List<String> tableCols = levelTableService.listColsByLevelId(level.getId());
        List<Map<String,Object>> data=universalTableService.listNotLeafItemInfo(tableName,tableCols);
        //data是<列名，具体值>的list
        //对bool值需要修改为是/否，否则前端不显示
        List<String> boolCols=levelTableService.listBoolColsById(level.getId());
        modifyBool(data,boolCols);
        //去除名字前面的随机数
        SubString.subStringList(data);
        return R.ok().put("data",data).put("levelId",level.getId());
    }

     /**
     * 获取第二层级的页面左侧的信息，需要名称、id,这里的一定不是叶子，因此不取其它属性
     * 应当在用户点击了第一层级的具体item后进行
     * @param id    project的id
     * @param page  分页信息
     * @param size  分页信息
     * @return
     */
    @RequestMapping(value={"/getRootLevelWithLimit","/getRootLeafNotItemWithLimit"})
    public R getRootLeafNotItemWithLimit(@RequestParam Long id,@RequestParam("page") Integer page,@RequestParam("size") Integer size){
        //1.获取所有parent_id=0,并且project_id为所选id,并且enabled=1的level，应该只有一个
        List<LevelEntity> candidateLevel=levelService.getRootLevel(id);
        LevelEntity level=candidateLevel.get(0);
        //2.获取该level的表，并且从该表中查询所有数据
        //因为最后一层（测点）是不可操作的，我们可选的是倒数第二层，因此这里不应该展示任何叶子节点
        String tableName=level.getTableName();
        //为了显示所有信息，这里需要获取列字段
        List<String> tableCols = levelTableService.listColsByLevelId(level.getId());
        List<Map<String,Object>> data=universalTableService.listNotLeafItemInfo(tableName,tableCols);
        //data是<列名，具体值>的list
        //对bool值需要修改为是/否，否则前端不显示
        List<String> boolCols=levelTableService.listBoolColsById(level.getId());
        modifyBool(data,boolCols);
        //去除名字前面的随机数
        SubString.subStringList(data);
        //分页筛选
        page=(page-1)*size;
        List<Map<String,Object>> subData= CollectionUtil.sub(data,page,page+size);
        return R.ok().put("data",subData).put("levelId",level.getId()).put("count",data.size());
    }

    /**
     * 获取第二层级的页面右侧的信息，需要获取所有的数据进行展示
     * 前端逻辑1.用户点击了第一层级的具体item2.前端获取列名3.执行该函数，将数据对应上列，填入表中
     * @param id    project的id
     * @return
     */
    @RequestMapping(value = {"/getRootLeafLevel","/getRootLeafItem"})
    public R getRootLeafItem(@RequestParam Long id){
        //1.获取所有parent_id=0,并且project_id为所选id,并且enabled=1的level，应该只有一个
        List<LevelEntity> candidateLevel=levelService.getRootLevel(id);
        LevelEntity level=candidateLevel.get(0);
        //2.获取该level的表，并且从该表中查询所有数据
        //这里展示的时页面右侧的值，即叶子节点的值
        String tableName=level.getTableName();
        //因为要获取所有的信息进行展示，因此需要获取列字段
        List<String> tableCols = levelTableService.listColsByLevelId(level.getId());
        List<Map<String,Object>> data=universalTableService.listLeafItem(tableName,tableCols);
        //data是<列名，具体值>的list
        //对bool值需要修改为是/否，否则前端不显示
        List<String> boolCols=levelTableService.listBoolColsById(level.getId());
        modifyBool(data,boolCols);
        //去除名字前面的随机数
        SubString.subStringList(data);
        return R.ok().put("data",data).put("levelId",level.getId());
    }

    /**
     * 获取第二层级的页面右侧的信息，需要获取所有的数据进行展示
     * 前端逻辑1.用户点击了第一层级的具体item2.前端获取列名3.执行该函数，将数据对应上列，填入表中
     * @param id    project的id
     * @param page  分页信息
     * @param size  分页信息
     * @return
     */
    @RequestMapping(value = {"/getRootLeafLevelWithLimit","/getRootLeafItemWithLimit"})
    public R getRootLeafItemWithLimit(@RequestParam Long id,@RequestParam("page") Integer page,@RequestParam("size") Integer size){
        //1.获取所有parent_id=0,并且project_id为所选id,并且enabled=1的level，应该只有一个
        List<LevelEntity> candidateLevel=levelService.getRootLevel(id);
        LevelEntity level=candidateLevel.get(0);
        //2.获取该level的表，并且从该表中查询所有数据
        //这里展示的时页面右侧的值，即叶子节点的值
        String tableName=level.getTableName();
        //因为要获取所有的信息进行展示，因此需要获取列字段
        List<String> tableCols = levelTableService.listColsByLevelId(level.getId());
        List<Map<String,Object>> data=universalTableService.listLeafItem(tableName,tableCols);
        //data是<列名，具体值>的list
        //对bool值需要修改为是/否，否则前端不显示
        List<String> boolCols=levelTableService.listBoolColsById(level.getId());
        modifyBool(data,boolCols);
        //去除名字前面的随机数
        SubString.subStringList(data);
        //分页筛选
        page=(page-1)*size;
        List<Map<String,Object>> subData= CollectionUtil.sub(data,page,page+size);
        return R.ok().put("data",subData).put("levelId",level.getId()).put("count",data.size());
    }

    /**
     * 获取第三层级及以后的所有子层级信息
     * @param tableId   当前点击的item所在层级id（parent_table_id)
     * @param id        当前点击的item的id(parent_row_id)
     * @return levelId是下一层级，即子层级的id
     */
    @RequestMapping("/getOtherAllItem")
    public R getOtherAllItem(@RequestParam Long tableId,@RequestParam Long id){
        //以防万一，采用三条件查询
        //1.获取子表id
        LevelEntity sonTable= levelService.getEnabledSon(tableId);
        //2.获取选中的item的相关子item的id
        List<LevelRelationEntity> sonRelaitons= levelRelationService.selectByParentAndSonTable(tableId,id,sonTable.getId());
        List<Long> sonIds=new ArrayList<>();
        for(LevelRelationEntity sonRelaiton:sonRelaitons){
            sonIds.add(sonRelaiton.getSonRowId());
        }
        if(sonIds.isEmpty()){
            List<Map<String,Object>> data=new ArrayList<>();
            return R.ok().put("data",data).put("levelId",sonTable.getId());
        }
        //3.在表中获取对应的获取子节点信息
        List<String> tableCols = levelTableService.listColsByLevelId(sonTable.getId());
        List<Map<String,Object>> data=universalTableService.listBySonIdsNotLimit(sonTable.getTableName(),tableCols,sonIds);
        SubString.subStringList(data);
        return R.ok().put("data",data).put("levelId",sonTable.getId());
    }

    /**
     * 获取第三层级及以后的所有子层级信息
     * @param tableId   当前点击的item所在层级id（parent_table_id)
     * @param id        当前点击的item的id(parent_row_id)
     * @return levelId是下一层级，即子层级的id
     */
    @RequestMapping("/getOtherAllItemWithLimit")
    public R getOtherAllItemWithLimit(@RequestParam Long tableId,@RequestParam Long id,@RequestParam("page") Integer page,@RequestParam("size") Integer size){
        //以防万一，采用三条件查询
        //1.获取子表id
        LevelEntity sonTable= levelService.getEnabledSon(tableId);
        //2.获取选中的item的相关子item的id
        List<LevelRelationEntity> sonRelaitons= levelRelationService.selectByParentAndSonTable(tableId,id,sonTable.getId());
        List<Long> sonIds=new ArrayList<>();
        for(LevelRelationEntity sonRelaiton:sonRelaitons){
            sonIds.add(sonRelaiton.getSonRowId());
        }
        if(sonIds.isEmpty()){
            List<Map<String,Object>> data=new ArrayList<>();
            return R.ok().put("data",data).put("levelId",sonTable.getId());
        }
        //3.在表中获取对应的获取子节点信息
        List<String> tableCols = levelTableService.listColsByLevelId(sonTable.getId());
        List<Map<String,Object>> data=universalTableService.listBySonIds(sonTable.getTableName(),tableCols,sonIds,page,size);
        SubString.subStringList(data);
        return R.ok().put("data",data).put("levelId",sonTable.getId()).put("count",sonIds.size());
    }

    /**
     * 获取第三层级以及之后的左侧信息
     * @param tableId   选择的item所在层级的id
     * @param id        选择的item的id
     * @return
     */
    @RequestMapping(value = {"/getSonLevel","/getOtherNotLeafItem"})
    public R getOtherNotLeafItem(@RequestParam Long tableId,@RequestParam Long id){
        //1.获取选中的item的相关子item
        List<LevelRelationEntity> levelRelationEntities= levelRelationService.selectByParent(tableId,id);
        //2.获取子表名
        LevelEntity sonLevel=levelService.getEnabledSon(tableId);
        String sonTableName=sonLevel.getTableName();
        //3.在表中获取对应的非叶子节点信息
        List<String> tableCols = levelTableService.listColsByLevelId(sonLevel.getId());
        List<Map<String,Object>> candidateItem=universalTableService.listNotLeafItemInfo(sonTableName,tableCols);
        //4.通过检查levelRelationEntities和candidateItem中的重合部分，获取目标item,为了加速，用了HashMap
        List<Map<String,Object>> data=new ArrayList<>();
        //用一个map装所有的item，之后遍历关系，将其中的item信息取出，发给前端
        HashMap<Object,Object> cItemId_lRelationSonId=new HashMap<>();
        for(int i=0;i<candidateItem.size();i++){
            cItemId_lRelationSonId.put(candidateItem.get(i).get("id"),i);
        }
        for(LevelRelationEntity levelRelation:levelRelationEntities){
            if(cItemId_lRelationSonId.get(levelRelation.getSonRowId())!=null){
                int itemId= (int) cItemId_lRelationSonId.get(levelRelation.getSonRowId());
                data.add(candidateItem.get(itemId));
            }
        }
        //data是<列名，具体值>的list
        //对bool值需要修改为是/否，否则前端不显示
        List<String> boolCols=levelTableService.listBoolColsById(sonLevel.getId());
        modifyBool(data,boolCols);
        //去除名字前面的随机数
        SubString.subStringList(data);
        return R.ok().put("data",data).put("levelId",sonLevel.getId());
    }

    /**
     * 获取第三层级以及之后的左侧信息
     * @param tableId   选择的item所在层级的id
     * @param id        选择的item的id
     * @param page      分页条件
     * @param size      分页条件
     * @return
     */
    @RequestMapping(value = {"/getSonLevelWithLimit","/getOtherNotLeafItemWithLimit"})
    public R getOtherNotLeafItemWithLimit(@RequestParam Long tableId,@RequestParam Long id,@RequestParam("page") Integer page,@RequestParam("size") Integer size){
        //1.获取选中的item的相关子item
        List<LevelRelationEntity> levelRelationEntities= levelRelationService.selectByParent(tableId,id);
        //2.获取子表名
        LevelEntity sonLevel=levelService.getEnabledSon(tableId);
        String sonTableName=sonLevel.getTableName();
        //3.在表中获取对应的非叶子节点信息
        List<String> tableCols = levelTableService.listColsByLevelId(sonLevel.getId());
        List<Map<String,Object>> candidateItem=universalTableService.listNotLeafItemInfo(sonTableName,tableCols);
        //4.通过检查levelRelationEntities和candidateItem中的重合部分，获取目标item,为了加速，用了HashMap
        List<Map<String,Object>> data=new ArrayList<>();
        //用一个map装所有的item，之后遍历关系，将其中的item信息取出，发给前端
        HashMap<Object,Object> cItemId_lRelationSonId=new HashMap<>();
        for(int i=0;i<candidateItem.size();i++){
            cItemId_lRelationSonId.put(candidateItem.get(i).get("id"),i);
        }
        for(LevelRelationEntity levelRelation:levelRelationEntities){
            if(cItemId_lRelationSonId.get(levelRelation.getSonRowId())!=null){
                int itemId= (int) cItemId_lRelationSonId.get(levelRelation.getSonRowId());
                data.add(candidateItem.get(itemId));
            }
        }
        //data是<列名，具体值>的list
        //对bool值需要修改为是/否，否则前端不显示
        List<String> boolCols=levelTableService.listBoolColsById(sonLevel.getId());
        modifyBool(data,boolCols);
        //去除名字前面的随机数
        SubString.subStringList(data);
        //进行数据量限制
        page=(page-1)*size;
        List<Map<String,Object>> subData= CollectionUtil.sub(data,page,page+size);
        return R.ok().put("data",subData).put("levelId",sonLevel.getId()).put("count",data.size());
    }

    /**
     * 获取一个item的叶子子节点,即获取第三层级以及以后的右面信息
     * @param tableId 该item所在的层级的id
     * @param id    选中的item的id
     */
    @RequestMapping(value = {"/getNotLeafItemByParent","/getOtherLeafItem"})    //第一个url是bug，但是已经使用了，就不修改了
    public R getOtherLeafItem(@RequestParam Long tableId,@RequestParam Long id){
        //1.获取选中的item的相关子item
        List<LevelRelationEntity> levelRelationEntities= levelRelationService.selectByParent(tableId,id);
        //2.获取子表名
        LevelEntity sonLevel=levelService.getEnabledSon(tableId);
        String sonTableName=sonLevel.getTableName();
        //3.在表中获取对应的叶子节点信息
        List<String> tableCols = levelTableService.listColsByLevelId(sonLevel.getId());
        List<Map<String,Object>> candidateItem=universalTableService.listLeafItem(sonTableName,tableCols);
        //4.通过检查levelRelationEntities和candidateItem中的重合部分，获取目标item,为了加速，用了HashMap
        List<Map<String,Object>> data=new ArrayList<>();
        //用一个map装所有的item，之后遍历关系，将其中的item信息取出，发给前端
        HashMap<Object,Object> cItemId_lRelationSonId=new HashMap<>();
        for(int i=0;i<candidateItem.size();i++){
            cItemId_lRelationSonId.put(candidateItem.get(i).get("id"),i);
        }
        for(LevelRelationEntity levelRelation:levelRelationEntities){
            if(cItemId_lRelationSonId.get(levelRelation.getSonRowId())!=null) {
                int itemId = (int) cItemId_lRelationSonId.get(levelRelation.getSonRowId());
                data.add(candidateItem.get(itemId));
            }
        }
        //data是<列名，具体值>的list
        //对bool值需要修改为是/否，否则前端不显示
        List<String> boolCols=levelTableService.listBoolColsById(sonLevel.getId());
        modifyBool(data,boolCols);
        //去除名字前面的随机数
        SubString.subStringList(data);
        return R.ok().put("data",data).put("levelId",sonLevel.getId());
    }

    /**
     * 获取一个item的叶子子节点,即获取第三层级以及以后的右面信息
     * @param tableId 该item所在的层级的id
     * @param id    选中的item的id
     * @param page  分页条件
     * @param size  分页条件
     * @return
     */
    @RequestMapping("/getOtherLeafItemWithLimit")
    public R getOtherLeafItemWithLimit(@RequestParam Long tableId,@RequestParam Long id,@RequestParam("page") Integer page,@RequestParam("size") Integer size){
        //1.获取选中的item的相关子item
        List<LevelRelationEntity> levelRelationEntities= levelRelationService.selectByParent(tableId,id);
        //2.获取子表名
        LevelEntity sonLevel=levelService.getEnabledSon(tableId);
        String sonTableName=sonLevel.getTableName();
        //3.在表中获取对应的叶子节点信息
        List<String> tableCols = levelTableService.listColsByLevelId(sonLevel.getId());
        List<Map<String,Object>> candidateItem=universalTableService.listLeafItem(sonTableName,tableCols);
        //4.通过检查levelRelationEntities和candidateItem中的重合部分，获取目标item,为了加速，用了HashMap
        List<Map<String,Object>> data=new ArrayList<>();
        //用一个map装所有的item，之后遍历关系，将其中的item信息取出，发给前端
        HashMap<Object,Object> cItemId_lRelationSonId=new HashMap<>();
        for(int i=0;i<candidateItem.size();i++){
            cItemId_lRelationSonId.put(candidateItem.get(i).get("id"),i);
        }
        for(LevelRelationEntity levelRelation:levelRelationEntities){
            if(cItemId_lRelationSonId.get(levelRelation.getSonRowId())!=null) {
                int itemId = (int) cItemId_lRelationSonId.get(levelRelation.getSonRowId());
                data.add(candidateItem.get(itemId));
            }
        }
        //data是<列名，具体值>的list
        //对bool值需要修改为是/否，否则前端不显示
        List<String> boolCols=levelTableService.listBoolColsById(sonLevel.getId());
        modifyBool(data,boolCols);
        //去除名字前面的随机数
        SubString.subStringList(data);
        //进行数据量限制
        page=(page-1)*size;
        List<Map<String,Object>> subData= CollectionUtil.sub(data,page,page+size);
        return R.ok().put("data",subData).put("levelId",sonLevel.getId()).put("count",data.size());
    }

    /**
     * 用于将数据中的true/false转换为是/否
     * @param data  待转化的数据
     * @param boolCols  数据中需要被转化的列
     */
    private void modifyBool(List<Map<String,Object>> data,List<String> boolCols){
        for(Map<String,Object> map :data)
        {
            for(String col: boolCols)
            {
                if((boolean) map.get(col))
                {
                    map.put(col,"是");
                }
                else
                    map.put(col,"否");
            }
        }
    }
}
