package com.gz.service.system.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.gz.common.DataGlobalVariable;
import com.gz.dto.system.ArchivesTreeDTO;
import com.gz.dto.system.MenuDTO;
import com.gz.dto.system.MenuRoleDTO;
import com.gz.mapper.system.ArchivesTreeMapper;
import com.gz.mapper.system.MenuRoleMapper;
import com.gz.service.system.ArchivesTreeService;
import com.gz.utils.JwtUtils;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.beans.ParameterDescriptor;
import java.util.ArrayList;
import java.util.List;

/**
 * @author LiuchangLan
 * @date 2021/2/23 15:50
 */
@Service
public class ArchivesTreeServiceImpl implements ArchivesTreeService {

    @Resource
    private ArchivesTreeMapper mapper;

    @Resource
    private MenuRoleMapper menuRoleMapper;


    @Override
    public Integer insert(ArchivesTreeDTO dto) {
        dto.setCreated(JwtUtils.getCurrentUserJwtPayload().getId());
        return mapper.insertSelective(dto);
    }

    @Override
    public Integer delete(Integer id) {
        return mapper.deleteByPrimaryKey(id);
    }

    @Override
    public Integer update(ArchivesTreeDTO dto) {
        dto.setUpdated(JwtUtils.getCurrentUserJwtPayload().getId());
        return mapper.updateByPrimaryKeySelective(dto);
    }

    @Override
    public List<ArchivesTreeDTO> selectAll() {
        return mapper.selectAll();
    }

    @Override
    public ArchivesTreeDTO selectByPrimaryKey(Integer id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public List<ArchivesTreeDTO> selectByOrder() {
        Example example = new Example(ArchivesTreeDTO.class);
        example.setOrderByClause("sort ASC");
        return mapper.selectByExample(example);
    }

    @Override
    public List<Tree<String>> selectTree() {
        List<ArchivesTreeDTO> menuDTOS = mapper.selectAllByRole(JwtUtils.getCurrentUserJwtPayload().getRoleId());
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        treeNodeConfig.setIdKey("id");
        // 最大递归深度
        treeNodeConfig.setDeep(3);

        //转换器
        List<Tree<String>> treeNodes = TreeUtil.build(menuDTOS, "-1", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId().toString());
                    tree.setParentId(treeNode.getParentId().toString());
                    tree.setName(treeNode.getTitle());
                    tree.putExtra("title", treeNode.getTitle() + treeNode.getCode());
                    tree.putExtra("code", treeNode.getCode());
                    tree.putExtra("spread",true);
                });
        return treeNodes;
    }

    @Override
    public void upMove(Integer id) {
        // 获取当前要上移的对象
        ArchivesTreeDTO archivesTreeDTO = mapper.selectByPrimaryKey(id);
        // 查询同级对象
        Example example = new Example(ArchivesTreeDTO.class);
        example.setOrderByClause("sort ASC");
        example.createCriteria().andEqualTo("parentId", archivesTreeDTO.getParentId());
        List<ArchivesTreeDTO> archivesTreeDTOS = mapper.selectByExample(example);
        for (int i = 0; i < archivesTreeDTOS.size(); i++) {
            ArchivesTreeDTO curr = archivesTreeDTOS.get(i);
            // 找到当前对象
            if (curr.getId().equals(id)) {
                // 已经是第一个 跳过
                if (i == 0) {
                    return;
                } else {
                    // 获取上一个
                    ArchivesTreeDTO prev = archivesTreeDTOS.get(i - 1);
                    if (curr.getSort().equals(prev)) {
                        // 两个排序相同 则减一
                        curr.setSort(curr.getSort() - 1);
                    } else {
                        // 不相同则互换
                        Integer currIndex = curr.getSort();
                        curr.setSort(prev.getSort());
                        prev.setSort(currIndex);
                    }
                    mapper.updateByPrimaryKey(prev);
                    mapper.updateByPrimaryKey(curr);
                }
            }
        }
    }

    @Override
    public void downMove(Integer id) {
        // 获取当前要上移的对象
        ArchivesTreeDTO archivesTreeDTO = mapper.selectByPrimaryKey(id);
        // 查询同级对象
        Example example = new Example(ArchivesTreeDTO.class);
        example.setOrderByClause("sort ASC");
        example.createCriteria().andEqualTo("parentId", archivesTreeDTO.getParentId());
        List<ArchivesTreeDTO> archivesTreeDTOS = mapper.selectByExample(example);
        for (int i = 0; i < archivesTreeDTOS.size(); i++) {
            ArchivesTreeDTO curr = archivesTreeDTOS.get(i);
            // 找到当前对象
            if (curr.getId().equals(id)) {
                // 已经是最后一个 跳过
                if (i == archivesTreeDTOS.size() - 1) {
                    return;
                } else {
                    // 获取下一个
                    ArchivesTreeDTO prev = archivesTreeDTOS.get(i + 1);
                    if (curr.getSort().equals(prev)) {
                        // 两个排序相同 则减一
                        curr.setSort(curr.getSort() + 1);
                    } else {
                        // 不相同则互换
                        Integer currIndex = curr.getSort();
                        curr.setSort(prev.getSort());
                        prev.setSort(currIndex);
                    }
                    mapper.updateByPrimaryKey(prev);
                    mapper.updateByPrimaryKey(curr);
                }
            }
        }
    }


    @Override
    public List<ArchivesTreeDTO> selectChildById(Integer id) {
        ArchivesTreeDTO param = new ArchivesTreeDTO();
        param.setParentId(id);
        // 查询子集
        List<ArchivesTreeDTO> select = mapper.select(param);
        // 无子集就返回自己
        if (select.size() > 0){
            return select;
        }else {
            return new ArrayList<ArchivesTreeDTO>(){{
                add(mapper.selectByPrimaryKey(id));
            }};
        }
    }

    @Override
    public ArchivesTreeDTO selectParentByCode(String code) {
        ArchivesTreeDTO archivesTreeDTO = mapper.selectParentByCode(code);
        if (archivesTreeDTO == null){
            ArchivesTreeDTO param = new ArchivesTreeDTO();
            param.setCode(code);
            return mapper.selectOne(param);
        }
        return archivesTreeDTO;
    }

    @Override
    public List<Tree<String>> selectArchiveRole(Integer roleId) {

        // 查询已有权限列表
        MenuRoleDTO dto = new MenuRoleDTO();
        dto.setRoleId(roleId);
        dto.setRoleType(DataGlobalVariable.ROLE_TYPE_ARCHIVE_TREE);
        List<MenuRoleDTO> select = menuRoleMapper.select(dto);
        // 所有档案树
        List<ArchivesTreeDTO> archiveTrees = mapper.selectAll();
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        treeNodeConfig.setIdKey("id");
        // 最大递归深度
        treeNodeConfig.setDeep(3);

        //转换器
        List<Tree<String>> treeNodes = TreeUtil.build(archiveTrees, "-1", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId().toString());
                    tree.setParentId(treeNode.getParentId().toString());
                    tree.setName(treeNode.getTitle());
                    tree.putExtra("title", treeNode.getTitle());

                    for (MenuRoleDTO menuRoleDTO : select) {
                        boolean flag = false;
                        // 判断是否有子元素
                        for (ArchivesTreeDTO menuDTO1 : archiveTrees) {
                            if (menuDTO1.getParentId().equals(treeNode.getId())) {
                                flag = true;
                                break;
                            }
                        }
                        // 有权限 并且没有子元素的默认选中
                        if (menuRoleDTO.getMenuId().equals(treeNode.getId()) && !flag) {
                            flag = true;
                            tree.putExtra("checked", true);
                            break;
                        }
                    }
                });
        return treeNodes;
    }
}
