package com.tykj.dev.device.packing.service.impl;

import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.blockcha.subject.entity.BcHash;
import com.tykj.dev.blockcha.subject.service.BlockChainUtil;
import com.tykj.dev.config.TaskBeanConfig;
import com.tykj.dev.config.base.DeviceLifeStatus;
import com.tykj.dev.config.cache.ConfigCache;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
import com.tykj.dev.device.library.service.DeviceLibraryService;
import com.tykj.dev.device.library.service.DeviceLogService;
import com.tykj.dev.device.library.subject.Dto.DeviceLogDto;
import com.tykj.dev.device.library.subject.domin.DeviceLibrary;
import com.tykj.dev.device.library.subject.domin.DeviceLog;
import com.tykj.dev.device.library.subject.vo.Script;
import com.tykj.dev.device.packing.repository.PackingLibraryDao;
import com.tykj.dev.device.packing.service.PackingLibraryService;
import com.tykj.dev.device.packing.service.PackingLogService;
import com.tykj.dev.device.packing.subject.domin.PackingLibrary;
import com.tykj.dev.device.packing.subject.domin.PackingLog;
import com.tykj.dev.device.packing.subject.vo.*;
import com.tykj.dev.device.user.read.service.MessageService;
import com.tykj.dev.device.user.read.subject.bto.MessageBto;
import com.tykj.dev.device.user.subject.entity.Units;
import com.tykj.dev.device.user.subject.service.UnitsService;
import com.tykj.dev.device.user.subject.service.UserPublicService;
import com.tykj.dev.device.user.util.UserUtils;
import com.tykj.dev.misc.exception.ApiException;
import com.tykj.dev.misc.utils.*;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bytecode.Throw;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toMap;

/**
 * @author dengdiyi
 */
@Service
@Slf4j
public class PackingLibraryServiceImpl implements PackingLibraryService {

    @Autowired
    private PackingLibraryDao packingLibraryDao;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private BlockChainUtil blockChainUtil;

    @Autowired
    private DeviceLibraryService deviceLibraryService;

    @Autowired
    private DeviceLibraryDao deviceLibraryDao;

    @Autowired
    private ConfigCache configCache;

    @Autowired
    private PackingLogService packingLogService;

    @Autowired
    private UserPublicService userPublicService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private UnitsService unitsService;

    @Autowired
    @Qualifier("taskExecutor")
    Executor executor;

    @Autowired
    private DeviceLogService deviceLogService;
    @Override
    public PackingLibrary addEntity(PackingLibrary packingLibraryEntity) {
        PackingLibrary packingLibrary = packingLibraryDao.save(packingLibraryEntity);
        CompletableFuture.runAsync(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            PackingLibrary packingLibrary1 = getOne(packingLibrary.getId());
            BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(getOne(packingLibrary.getId())));
            String recordId = bcText.getData().getRecordID();
            packingLibrary1.setRecordId(recordId);
            packingLibraryDao.save(packingLibrary1);
        });
        return packingLibrary;
    }

    /**
     * @param packingLibraries 列装异步上链
     */
    @Override
    @Async
    public void sendHash(List<PackingLibrary> packingLibraries) {
        packingLibraries.forEach(packingLibrary -> {
            BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(packingLibrary));
            String recordId = bcText.getData().getRecordID();
            packingLibrary.setRecordId(recordId);
            update(packingLibrary);
        });
    }

    @Override
    public Page<PackingLibrary> getPage(PackingLibrarySelectVo packingLibrarySelectVo, Pageable pageable) {
        return packingLibraryDao.findAll(getSelectSpecification5(packingLibrarySelectVo), pageable);
    }

    @Override
    public List<PackingLibrary> getInvalidPage(PackingLibrarySelectVo packingLibrarySelectVo, Pageable pageable) {
        List<PackingLibrary> packingLibraryEntities = packingLibraryDao.findAll(getSelectSpecification2(packingLibrarySelectVo),pageable.getSort());
            //取出退装的model
            List<String> models = packingLibraryEntities.stream().map(PackingLibrary::getModel).distinct().collect(Collectors.toList());
            //取出相同型号的目录
            List<PackingLibrary> byModelAndIsRoot = findByModelAndIsRoot(models);
            packingLibraryEntities.addAll(byModelAndIsRoot);
            packingLibraryEntities.forEach(PackingLibrary::setConfigName);
        return packingLibraryEntities;
    }

    @Override
    public List<PackingLibrary> getList(PackingLibrarySelectVo packingLibrarySelectVo) {
        List<PackingLibrary> packingLibraryEntities = packingLibraryDao.findAll(getSelectSpecification22(packingLibrarySelectVo));
        packingLibraryEntities.forEach(PackingLibrary::setConfigName);
        //返回父子结构
        Map<Integer, PackingLibrary> nodeCollect =
                packingLibraryEntities.stream().collect(Collectors.toMap(PackingLibrary::getId, packingLibraryEntity -> packingLibraryEntity));
        return GetTreeUtils.parseTreeFromDown(
                packingLibraryEntities,
                PackingLibrary::getId,
                packingLibraryEntity -> Optional.ofNullable(nodeCollect.get(packingLibraryEntity.getPartParentId())),
                PackingLibrary::addChildNode
        ).stream().sorted(Comparator.comparing(PackingLibrary::getModel)).collect(Collectors.toList());
    }

    @Override
    public List<PackingLibrary> getList1(PackingLibrarySelectVo packingLibrarySelectVo) {
        List<PackingLibrary> packingLibraryEntities = packingLibraryDao.findAll(getSelectSpecification(packingLibrarySelectVo));
        return packingLibraryEntities;
    }


    @Override
    public List<Integer> getTypeList() {
        List<PackingLibrary> list = packingLibraryDao.findAll();
        Set<Integer> s = new HashSet<>();
        for (PackingLibrary d : list) {
            s.add(d.getType());
        }
        return new ArrayList<>(s);
    }

    @Override
    public List<String> getModelList() {
        List<PackingLibrary> list = packingLibraryDao.findAllByIsRootAndPackingStatus(1,2).stream().sorted(Comparator.comparing(PackingLibrary::getShowOrder,Comparator.nullsLast(Integer::compareTo)).thenComparing(PackingLibrary::getModel)).collect(Collectors.toList());

        List<String> s = new ArrayList<>();
        for (PackingLibrary d : list) {
            s.add(d.getModel());
        }
        return s;
    }

    @Override
    public List<PackingLibrary> selectAllPart(Integer id) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("isPart", 1);
        predicateBuilder.eq("partParentId", id);
        return packingLibraryDao.findAll(predicateBuilder.build());
    }

    @Override
    public PackingLibrary update(PackingLibrary packingLibraryEntity) {
        PackingLibrary packingLibrary = packingLibraryDao.save(packingLibraryEntity);
        CompletableFuture.runAsync(()-> blockChainUtil.appendHash(JacksonUtil.toJSon(packingLibrary),packingLibrary.getRecordId()), TaskBeanConfig.getThreadPoolTaskScheduler());
        return packingLibrary;
    }

    @Override
    public PackingLibrary getOne(Integer id) {
        Optional<PackingLibrary> byId = packingLibraryDao.findById(id);
        if (!byId.isPresent()) {
            throw new ApiException(ResultUtil.failed("id不存在"));
        } else {
            return byId.get().setConfigName();
        }
    }

    @Override
    public List<PackingLibrary> getPackingDetail(Integer id) {
        Optional<PackingLibrary> byId = packingLibraryDao.findById(id);
        if (!byId.isPresent()) {
            throw new ApiException(ResultUtil.failed("id不存在"));
        } else {
            //添加主件
            List<PackingLibrary> libraryEntities = new ArrayList<>();
            libraryEntities.add(byId.get().setConfigName());
            //添加配件信息
            List<PackingLibrary> p = packingLibraryDao.findAll(getSelectSpecification3(id));
            p.forEach(PackingLibrary::setConfigName);
            libraryEntities.addAll(p);
            return libraryEntities;
        }
    }

    @Override
    public List<PackingLibrary> getInvalidDetail(Integer id) {
        Optional<PackingLibrary> byId = packingLibraryDao.findById(id);
        if (!byId.isPresent()) {
            throw new ApiException(ResultUtil.failed("id不存在"));
        } else {
            //添加主件
            List<PackingLibrary> libraryEntities = new ArrayList<>();
            libraryEntities.add(byId.get().setConfigName());
            //添加配件信息
            List<PackingLibrary> p = packingLibraryDao.findAll(getSelectSpecification4(id));
            p.forEach(PackingLibrary::setConfigName);
            libraryEntities.addAll(p);
            return libraryEntities;
        }
    }

    @Override
    public void delete(Integer id) {
        PackingLibrary packingLibrary = getOne(id);
        packingLibrary.setPackingStatus(4);
//        packingLibrary.setExitTime(Timestamp.from(new Date().toInstant()));
        if (packingLibrary.getIsRoot()==1) {
            packingLibrary.setShowOrder(9999);
        }
        update(packingLibrary);
        //添加列装日志
        PackingLog packingLog = new PackingLog();
        packingLog.setRemark("手动删除列装");
        packingLog.setPackingId(id);
        packingLogService.add(packingLog);
    }

    /**
     * @param selectPack 列装查询vo
     *                   获取父子结构列装列表
     */
    @Override
    public List<PackingLibrary> getInsertList(SelectPack selectPack) {
        final String model = selectPack.getModel();
        final String content = selectPack.getContent();
        final String name = selectPack.getName();
        final Integer status = selectPack.getStatus();
        final Integer secretLevel = selectPack.getSecretLevel();
        List<PackingLibrary> packingLibraryEntities = packingLibraryDao.findAll(getSelectSpecification6()).stream().sorted(Comparator.comparing(PackingLibrary::getName)).collect(Collectors.toList());
//                .stream().filter(packingLibrary -> {
//            boolean isSameModel = model == null || packingLibrary.getModel().equals(model);
//            boolean isSameName = name == null || packingLibrary.getName().equals(name);
//            boolean isSameStatus = status == null || packingLibrary.getStatus().equals(status);
//            boolean isSameSecretLevel = secretLevel == null || packingLibrary.getSecretLevel().equals(secretLevel);
//            boolean isContainContent = content == null
//                    || packingLibrary.getModel().contains(content)
//                    || configCache.getInvisibleRangeMap().get(packingLibrary.getInvisibleRange()).contains(content)
//                    || configCache.getSecretLevelMap().get(packingLibrary.getSecretLevel()).contains(content);
//            return isSameModel && isSameName && isSameStatus && isSameSecretLevel && isContainContent;
//        }).collect(Collectors.toList());
        packingLibraryEntities.forEach(PackingLibrary::setConfigName);
        //返回父子结构
        Map<Integer, PackingLibrary> nodeCollect =
                packingLibraryEntities.stream().collect(Collectors.toMap(PackingLibrary::getId, packingLibrary -> packingLibrary));
        return GetTreeUtils.parseTreeFromDown(
                packingLibraryEntities,
                PackingLibrary::getId,
                packingLibrary -> Optional.ofNullable(nodeCollect.get(packingLibrary.getPartParentId())),
                PackingLibrary::addChildNode
        ).stream().filter(packingLibrary -> {
            boolean isSameModel = model == null || packingLibrary.getModel().equals(model);
            boolean isSameName = name == null || packingLibrary.getName().equals(name);
            boolean isSameStatus = status == null || packingLibrary.getStatus().equals(status);
            boolean isSameSecretLevel = secretLevel == null || packingLibrary.getSecretLevel().equals(secretLevel);
            boolean isContainContent = content == null
                    || packingLibrary.getModel().contains(content)
                    || configCache.getInvisibleRangeMap().get(packingLibrary.getInvisibleRange()).contains(content)
                    || configCache.getSecretLevelMap().get(packingLibrary.getSecretLevel()).contains(content);
            return isSameModel && isSameName && isSameStatus && isSameSecretLevel && isContainContent;
        }).sorted(Comparator.comparing(PackingLibrary::getShowOrder,Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
    }

//    /**
//     * @param id 列装主键id
//     *           通过id逻辑删除该列装以及所有子列装
//     */
//    @Override
//    @Transient
//    public void deleteAll(Integer id) {
//        PackingLibrary packingLibrary = getOne(id);
//        if (packingLibrary.getPackingStatus()==2) {
//            if (deviceLibraryDao.getAllByPackingId(id).size() > 0) {
//                throw new ApiException(ResponseEntity.status(20000).body("该列装型号已有装备,请进行退装操作"));
//            }
//            if (packingLibrary.getIsRoot() == 1) {
//                if (packingLibraryDao.findAllByPartParentIdAndPackingStatus(id, 2).size() > 0) {
//                    throw new ApiException(ResponseEntity.status(20000).body("该列装型号目录下存在列装装备"));
//                }
//                Integer order = packingLibrary.getShowOrder();
////                getInsertList(new SelectPack()).forEach(packingLibrary1 -> {
////                    if (packingLibrary1.getShowOrder() > order) {
////                        packingLibrary1.setShowOrder(packingLibrary1.getShowOrder() - 1);
////                        update(packingLibrary1);
////                    }
////                });
//            }
//            List<Integer> ids = packingLibraryDao.findAllByPartParentId(id).stream().map(PackingLibrary::getId).collect(Collectors.toList());
//            delete(id);
//            if (ids.size() > 0) {
//                ids.forEach(integer -> {
//                    if (deviceLibraryDao.getAllByPackingId(integer).size() > 0) {
//                        throw new ApiException(ResponseEntity.status(20000).body("该列装型号已有装备,请进行退装操作"));
//                    }
//                    deleteAll(integer);
//                });
//            }
//            //发送阅知信息
//            List<Integer> userIds = userPublicService.findOtherUser(userUtils.getCurrentUserId());
//            MessageBto messageBto = new MessageBto(0, 1, "手动删除列装", userIds, 0);
//            messageBto.setRecord(id.toString());
//            messageService.add(messageBto);
//        }
//    }

    /**
     * @param id 列装主键id
     *           通过id逻辑删除该列装以及所有子列装
     */
    @Override
    @Transient
    public void deleteAll(Integer id) {
        PackingLibrary packingLibrary = getOne(id);
        List<Integer> status = new ArrayList<>(Arrays.asList(DeviceLifeStatus.RETIRE.id,DeviceLifeStatus.DESTROYED.id,DeviceLifeStatus.SCRAP_I.id));
        List<DeviceLibrary> deviceLibraries = deviceLibraryDao.getAllByPackingId(id).stream()
                .filter(deviceLibrary -> !status.contains(deviceLibrary.getLifeStatus())).collect(Collectors.toList());
        if (packingLibrary.getPackingStatus()==2) {
            if (deviceLibraries.size() > 0) {
                throw new ApiException(ResponseEntity.status(20000).body("该列装型号已有装备,请进行退装操作"));
            }
            if (packingLibrary.getIsRoot() == 1) {
                if (packingLibraryDao.findAllByPartParentIdAndPackingStatus(id, 2).size() > 0) {
                    throw new ApiException(ResponseEntity.status(20000).body("该列装型号目录下存在列装装备"));
                }
            }
            List<Integer> ids = packingLibraryDao.findAllByPartParentId(id).stream().map(PackingLibrary::getId).collect(Collectors.toList());
            delete(id);
            if (ids.size() > 0) {
                ids.forEach(integer -> {
                    if (deviceLibraryDao.getAllByPackingId(integer).size()>0){
                        if (deviceLibraryDao.getAllByPackingId(integer).stream().noneMatch(deviceLibrary ->
                                status.contains(deviceLibrary.getLifeStatus()))) {
                            throw new ApiException(ResponseEntity.status(20000).body("该列装型号已有装备,请进行退装操作"));
                        }
                    }
                    deleteAll(integer);
                });
            }
//            if (ids.size() > 0) {
//                ids.forEach(integer -> {
//                    if (deviceLibraryDao.getAllByPackingId(integer).stream().allMatch(deviceLibrary ->
//                            status.contains(deviceLibrary.getLifeStatus()))) {
//                        throw new ApiException(ResponseEntity.status(20000).body("该列装型号已有装备,请进行退装操作"));
//                    }
//                    deleteAll(integer);
//                });
//            }
            //发送阅知信息
//            List<Integer> userIds = userPublicService.findOtherUser(userUtils.getCurrentUserId());
//            MessageBto messageBto = new MessageBto(0, 1, "手动删除列装", userIds, 0);
//            messageBto.setRecord(id.toString());
//            messageService.add(messageBto);
        }
    }

    /**
     * @param ids 列装主键id列表
     *            通过id将退装装备恢复到列装
     */
    @Override
    public void removeAll(List<Integer> ids) {
        for (Integer id:ids){
            PackingLibrary packingLibrary = getOne(id);
            packingLibrary.setPackingStatus(2);
            update(packingLibrary);
            //添加列装日志
            PackingLog packingLog = new PackingLog();
            packingLog.setRemark("恢复列装");
            packingLog.setPackingId(id);
            packingLogService.add(packingLog);
        }
        //发送阅知信息
        List<Integer> userIds = userPublicService.findOtherUser(userUtils.getCurrentUserId());
        MessageBto messageBto = new MessageBto(0,1,"恢复列装",userIds,0);
        messageBto.setRecord(StringSplitUtil.idListToString(ids));
        messageService.add(messageBto);
    }

//    /**
//     * @param ids 列装主键id列表
//     *            通过id将回收站装备清空删除
//     */
//    @Override
//    public void cleanAll(List<Integer> ids) {
//        for (Integer id:ids){
//            PackingLibrary packingLibrary = getOne(id);
//            packingLibrary.setDeleteTag(1);
//            update(packingLibrary);
//            //添加列装日志
//            PackingLog packingLog = new PackingLog();
//            packingLog.setRemark("回收站清空列装");
//            packingLog.setPackingId(id);
//            packingLogService.add(packingLog);
//        }
//        //发送阅知信息
//        List<Integer> userIds = userPublicService.findOtherUser(userUtils.getCurrentUserId());
//        MessageBto messageBto = new MessageBto(0,1,"回收站清空列装",userIds,0);
//        messageBto.setRecord(StringSplitUtil.idListToString(ids));
//        messageService.add(messageBto);
//    }

    /**
     * @param ids 列装主键id列表
     *            通过id将回收站装备清空删除
     */
    @Override
    public void cleanAll(List<Integer> ids) {
        List<DeviceLibrary> deviceLibraries = deviceLibraryDao.findAllByPackingIdIn(ids);
//        Map<String,String> map = new HashMap<>();
        if (deviceLibraries.size()>0){
//            map.put("error","该列装目录下存在装备,不能被删除");
            throw new ApiException("该列装目录下存在装备,不能被删除");
        }else {
            for (Integer id:ids){
                PackingLibrary packingLibrary = getOne(id);
                packingLibrary.setDeleteTag(1);
                update(packingLibrary);
                //添加列装日志
                PackingLog packingLog = new PackingLog();
                packingLog.setRemark("回收站清空列装");
                packingLog.setPackingId(id);
                packingLogService.add(packingLog);
            }
            //发送阅知信息
            List<Integer> userIds = userPublicService.findOtherUser(userUtils.getCurrentUserId());
            MessageBto messageBto = new MessageBto(0,1,"回收站清空列装",userIds,0);
            messageBto.setRecord(StringSplitUtil.idListToString(ids));
            messageService.add(messageBto);
        }

    }

    /**
     * 设置顺序的排序
     */
    @Override
    public List<PackingLibrary> setOrder(List<PackingLibrary> packingLibraries) {
        List<PackingLibrary> packingLibraryList = new ArrayList<>();
        for (int i =1;i<=packingLibraries.size();i++){
            PackingLibrary packingLibrary = packingLibraries.get(i-1);
            packingLibrary.setShowOrder(i);
            packingLibraryList.add(packingLibrary);
            update(packingLibrary);
        }
        return packingLibraryList;
    }

    @Override
    public List<Script> getDevcieScript(List<Integer> ids) {
        Map<Integer,DeviceLibrary> deviceLibraryMap = deviceLibraryService.getAllDeviceMap();
        List<Script> scripts = new ArrayList<>();
        List<DeviceLibrary> deviceLibraries = new ArrayList<>();
        ids.forEach(integer -> deviceLibraries.add(deviceLibraryMap.get(integer)));
        Map<Integer, List<DeviceLibrary>> map = deviceLibraries.stream().collect(groupingBy(DeviceLibrary::getPackingId));
        for (Integer packingId:map.keySet()){
            List<DeviceLibrary> deviceLibraryList = map.get(packingId);
            PackingLibrary packingLibrary = getOne(packingId);
            Script script = new Script();
            script.setId(packingId);
            script.setPartParentId(packingLibrary.getPartParentId());
            script.setInvisibleRange(packingLibrary.getInvisibleRangeName());
            script.setModel(packingLibrary.getModel());
            script.setName(packingLibrary.getName());
            script.setSecretLevel(packingLibrary.getSecretLevelName());
            script.setType(packingLibrary.getTypeName());
            script.setNum(deviceLibraryList.size());
            script.setSeqNumber(StringSplitUtil.stringListToString(DeviceSeqUtil.getContinuousSeqs(deviceLibraryList.stream().map(DeviceLibrary::getSeqNumber).collect(Collectors.toList()))));
            scripts.add(script);
        }
        Map<Integer, Script> nodeCollect =
                scripts.stream().collect(Collectors.toMap(Script::getId, script -> script));
        List<Script> scriptList = new ArrayList<>();
        List<Script> conList = GetTreeUtils.parseTreeFromDown(
                scripts,
                Script::getId,
                script -> Optional.ofNullable(nodeCollect.get(script.getPartParentId())),
                Script::addChildNode
        );
        for (Script s:conList) {
            addScript(scriptList,s);
        }
        return scriptList.stream().sorted(Comparator.comparing(Script::getLength).reversed()).collect(Collectors.toList());
    }

    @Override
    public List<Script> getDevcieAllotScript(List<Integer> ids) {
        Map<Integer,DeviceLibrary> deviceLibraryMap = deviceLibraryService.getAllDeviceMap();
        List<Script> scripts = new ArrayList<>();
        List<DeviceLibrary> deviceLibraries = new ArrayList<>();
        ids.forEach(integer -> deviceLibraries.add(deviceLibraryMap.get(integer)));
        Map<Integer, List<DeviceLibrary>> map = deviceLibraries.stream().collect(groupingBy(DeviceLibrary::getPackingId));
        for (Integer packingId:map.keySet()){
                List<DeviceLibrary> deviceLibraryList = map.get(packingId);
                PackingLibrary packingLibrary = getOne(packingId);
                packingLibrary.setConfigName();
                Script script = new Script();
                script.setId(packingId);
                script.setPartParentId(packingLibrary.getPartParentId());
                script.setInvisibleRange(packingLibrary.getInvisibleRangeName());
                script.setModel(packingLibrary.getModel());
                script.setName(packingLibrary.getName());
                script.setSecretLevel(packingLibrary.getSecretLevelName());
                script.setType(packingLibrary.getTypeName());
                script.setNum(deviceLibraryList.size());
                script.setAllotType(packingLibrary.getMatchingRangeName());
                script.setAllotTypeNum(packingLibrary.getMatchingRange());
                script.setSeqNumber(StringSplitUtil.stringListToString(DeviceSeqUtil.getContinuousSeqs(deviceLibraryList.stream().map(DeviceLibrary::getSeqNumber).collect(Collectors.toList()))));
                scripts.add(script);
        }
        Map<Integer, Script> nodeCollect =
                scripts.stream().collect(Collectors.toMap(Script::getId, script -> script));
        List<Script> scriptList = new ArrayList<>();
        List<Script> conList = GetTreeUtils.parseTreeFromDown(
                scripts,
                Script::getId,
                script -> Optional.ofNullable(nodeCollect.get(script.getPartParentId())),
                Script::addChildNode
        );
        for (Script s:conList) {
            addScript(scriptList,s);
        }
        scriptList.forEach(script -> script.setChilds(null));
        return scriptList.stream().sorted(Comparator.comparing(Script::getLength).reversed()).collect(Collectors.toList());
    }

    private void addScript(List<Script> scripts,Script script){
        scripts.add(script);
        if (script.getChilds()!=null&&script.getChilds().size()>0){
            script.getChilds().forEach(s -> addScript(scripts,s));
        }
    }

    /**
     * @param packingId 列装id
     * @param num       配发数量
     * @return 自动选择装备生成的序列号区间
     * 配发按照序列号排序自动选择装备
     */
    @Override
    public AllotSeqs getAllotAutoSeqs(Integer packingId, Integer num) {
        AllotSeqs allotSeqs = new AllotSeqs();
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("ownUnit", userUtils.getCurrentUserUnitName());
        predicateBuilder.eq("lifeStatus", 2);
        predicateBuilder.eq("packingId", packingId);
        List<DeviceLibrary> deviceLibraries = deviceLibraryDao.findAll(predicateBuilder.build()).stream().sorted(Comparator.comparing(DeviceLibrary::getSeqNumber,Comparator.nullsLast(String::compareTo))).collect(Collectors.toList());
        List<String> seqs = deviceLibraries.stream().map(DeviceLibrary::getSeqNumber).collect(Collectors.toList());
        if (seqs.size()>=num) {
            allotSeqs.setStrings(Collections.singletonList(StringSplitUtil.stringListToString(DeviceSeqUtil.getContinuousSeqs(seqs.subList(0, num)))));
            allotSeqs.setIds(deviceLibraries.subList(0,num).stream().map(DeviceLibrary::getId).collect(Collectors.toList()));
            return allotSeqs;
        }
        else {
            throw new ApiException("选择数量大于在库数量");
        }
    }

    @Override
    public Integer getAllotNum(Integer packingId) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("ownUnit", userUtils.getCurrentUserUnitName());
        predicateBuilder.eq("lifeStatus", 2);
        predicateBuilder.eq("packingId", packingId);
        return deviceLibraryDao.findAll(predicateBuilder.build()).size();
    }

    @Override
    public List<PackingLibrary> setAllotNum(List<PackingLibrary> packingLibraries) {
        List<PackingLibrary> result = new ArrayList<>();
        packingLibraries.forEach(packingLibrary -> {
            packingLibrary.setDevNum(getAllotNum(packingLibrary.getId()));
            if (packingLibrary.getIsPart()==1){
                packingLibrary.setName("[附件]"+packingLibrary.getName());
            }
            result.add(packingLibrary);
            if (packingLibrary.getChilds()!=null&&packingLibrary.getChilds().size()>0){
                result.addAll(setAllotNum(packingLibrary.getChilds()));
            }
        });
        return result;
    }

    @Override
    public List<DeviceLibrary> getAllDevSeqs(Integer packingId) {
        List<String> unitNames = unitsService.findSuperiorUnitsList().stream().map(Units::getName).collect(Collectors.toList());
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        if (unitNames.size()>0) {
            predicateBuilder.notIn("ownUnit", unitNames.toArray());
        }
//        predicateBuilder.eq("lifeStatus", 2);
        predicateBuilder.eq("packingId", packingId);
        return deviceLibraryDao.findAll(predicateBuilder.build());
    }

    @Override
    public List<DeviceLibrary> getAllotDevSeqs(Integer packingId) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("ownUnit", userUtils.getCurrentUserUnitName());
        predicateBuilder.eq("locationUnit", userUtils.getCurrentUserUnitName());
        predicateBuilder.eq("lifeStatus", 2);
        predicateBuilder.eq("packingId", packingId);
        return deviceLibraryDao.findAll(predicateBuilder.build());
    }

    @Override
    public Boolean modelIsExist(String model) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("isRoot", 1);
        predicateBuilder.eq("model", model);
        return packingLibraryDao.findAll(predicateBuilder.build()).size()>0;
    }

    /**
     * @param id 列装主键id
     *           通过id修改该列装所有子列装型号
     */
    @Override
    public void changeAllModel(Integer id,String model) {
        PackingLibrary packingLibrary = getOne(id);
        //添加列装日志
        PackingLog packingLog = new PackingLog();
        packingLog.setRemark("将型号从"+packingLibrary.getModel()+"改为"+model);
        packingLog.setPackingId(id);
        packingLogService.add(packingLog);
        packingLibrary.setModel(model);
        update(packingLibrary);
        List<Integer> ids = packingLibraryDao.findAllByPartParentId(id).stream().map(PackingLibrary::getId).collect(Collectors.toList());
        ids.forEach(integer -> changeAllModel(integer,model));
    }

    @Override
    public Boolean nameIsExist(String model, String name ,Integer partParentId) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("isRoot", 0);
        predicateBuilder.eq("model", model);
        predicateBuilder.eq("name", name);
        predicateBuilder.eq("partParentId", partParentId);
        return packingLibraryDao.findAll(predicateBuilder.build()).size()>0;
    }

    @Override
    public Boolean nameIsExist1(String model, String name, Integer partParentId, Integer matchingRange) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("isRoot", 0);
        predicateBuilder.eq("model", model);
        predicateBuilder.eq("name", name);
        predicateBuilder.eq("partParentId", partParentId);
        predicateBuilder.eq("matchingRange", matchingRange);
        return packingLibraryDao.findAll(predicateBuilder.build()).size()>0;
    }

    @Override
    public Boolean matchingRangeIsExist(Integer parentId,Integer matchingRange,Integer type,Integer style,String name,Integer secretLevel,Integer invisibleRange) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("isRoot", 0);
        predicateBuilder.eq("partParentId", parentId);
        predicateBuilder.eq("matchingRange", matchingRange);
//        predicateBuilder.eq("type",type);
//        predicateBuilder.eq("style",style);
        predicateBuilder.eq("name",name);
//        predicateBuilder.eq("secretLevel",secretLevel);
//        predicateBuilder.eq("invisibleRange",invisibleRange);
        return packingLibraryDao.findAll(predicateBuilder.build()).size()>0;
    }

    /**
     * @param parentId 父列装id
     * @param matchingRange 配用范围
     * 查询对应横向或纵向列装
     */
    @Override
    public PackingLibrary findSamePacking(Integer parentId,Integer matchingRange,Integer type,Integer style,String name,Integer secretLevel,Integer invisibleRange) {

        List<PackingLibrary> packingLibraries = packingLibraryDao.findAllByPartParentIdAndMatchingRangeAndPackingStatusAndName(parentId,matchingRange,2,name);
        if (packingLibraries.isEmpty()){
            return null;
        }
        else {
            return packingLibraries.get(0);
        }
    }

    @Override
    public PackingLibrary findSamePackingInPackingStatus(Integer parentId, Integer matchingRange, Integer type, Integer style, String name, Integer secretLevel, Integer invisibleRange) {
        List<Integer> list = new ArrayList<>(Arrays.asList(2, 4));

        List<PackingLibrary> packingLibraries = packingLibraryDao.findAllByPartParentIdAndMatchingRangeAndPackingStatusInAndName(parentId,matchingRange,list,name);
        if (packingLibraries.isEmpty()){
            return null;
        }
        else {
            return packingLibraries.get(0);
        }
    }
//
//    @Override
//    public PackingLibrary findSamePackingByDel(Integer parentId, Integer matchingRange, Integer type, Integer style, String name, Integer secretLevel, Integer invisibleRange, Integer del) {
//        List<PackingLibrary> allByPartParentIdAndMatchingRangeAndPackingStatusAndNameAndDeleteTag = packingLibraryDao.findAllByPartParentIdAndMatchingRangeAndPackingStatusAndNameAndDeleteTag(parentId, matchingRange, 4, name, 1);
//        if (allByPartParentIdAndMatchingRangeAndPackingStatusAndNameAndDeleteTag.isEmpty()){
//            return null;
//        }else {
//            return allByPartParentIdAndMatchingRangeAndPackingStatusAndNameAndDeleteTag.get(0);
//        }
//    }

    @Override
    public List<PackingLibrary> findSamePacking1(Integer parentId, Integer matchingRange, Integer type, Integer style, String name, Integer secretLevel, Integer invisibleRange) {
        List<PackingLibrary> packingLibraries = packingLibraryDao.findAllByPartParentIdAndMatchingRangeAndPackingStatusAndName(parentId,matchingRange,2,name);
        if (packingLibraries.isEmpty()){
            return null;
        }
        else {
            return packingLibraries;
        }
    }


    /**
     * @param packingLibraries 父子结构列装
     *                         拆分父子结构列装
     */
    @Override
    public List<PackingLibrary> splitTree(List<PackingLibrary> packingLibraries) {
        List<PackingLibrary> resultList = new ArrayList<>();
        for (PackingLibrary p:packingLibraries){
            resultList.add(p);
            if (p.getChilds()!=null&&p.getChilds().size()>0){
                resultList.addAll(splitTree(p.getChilds()));
            }
        }
        return resultList;
    }

    /**
     * 判断是否有相同名称的列装装备，如果相同则可以进行新增
     */
    @Override
    public Boolean hasSamePack(Integer parentId, Integer type, Integer style, String name, Integer secretLevel, Integer invisibleRange) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("isRoot", 0);
        predicateBuilder.eq("partParentId", parentId);
        predicateBuilder.eq("name",name);
        return packingLibraryDao.findAll(predicateBuilder.build()).size()>0;
    }

    @Override
    public List<PackingLibrary> getAllByPartPackingId(Integer partPackingId) {
//        PredicateBuilder<PackingLibrary> and = Specifications.and();
//        and.eq("partParentId",partPackingId);
//        return packingLibraryDao.findAll(and.build());
        return packingLibraryDao.findAllByPartParentId(partPackingId);
    }

    @Override
    public Boolean addAllotPacking(PackingLibrary packingLibraryEntity) {
        //相同名称的同级列装
        Boolean aBoolean = hasSamePack(packingLibraryEntity.getPartParentId(), packingLibraryEntity.getType(), packingLibraryEntity.getStyle(), packingLibraryEntity.getName(), packingLibraryEntity.getSecretLevel(), packingLibraryEntity.getInvisibleRange());
        if (aBoolean){
            //同级列装是否有同级范围的
            Boolean matchingRangeIsExist = matchingRangeIsExist(packingLibraryEntity.getPartParentId(), packingLibraryEntity.getMatchingRange(), packingLibraryEntity.getType(), packingLibraryEntity.getStyle(), packingLibraryEntity.getName(), packingLibraryEntity.getSecretLevel(), packingLibraryEntity.getInvisibleRange());
            if (matchingRangeIsExist) {
                Map<String, Object> map = new HashMap<>();
                map.put("error", "型号" + packingLibraryEntity.getModel() + "下配用范围为" + configCache.getMatchingRangeMap().get(packingLibraryEntity.getMatchingRange()) + "的该装备已存在");
                return false;
            }
        }
        PackingLibrary packingLibrary1 = getOne(packingLibraryEntity.getPartParentId());
        if (packingLibrary1.getIsRoot()==1){
            //不是配件
            packingLibraryEntity.setIsPart(0);
            String message = "添加列装型号"+packingLibraryEntity.getModel()+"下的装备:"+packingLibraryEntity.getName();
            //发送阅知信息
            List<Integer> userIds = userPublicService.findOtherUser(userUtils.getCurrentUserId());
            MessageBto messageBto = new MessageBto(0,1,message,userIds,0);
            messageBto.setRecord(packingLibrary1.getId().toString());
            messageService.add(messageBto);
            //添加列装日志
            PackingLog packingLog = new PackingLog();
            packingLog.setRemark(message);
            packingLog.setPackingId(packingLibrary1.getId());
            packingLogService.add(packingLog);
        }
        else {
            //是配件
            packingLibraryEntity.setIsPart(1);
            String message = "添加列装型号"+packingLibraryEntity.getModel()+"下的装备附件:"+packingLibraryEntity.getName();
//            //添加业务日志
//            TaskLogBto taskLogBto2 = new TaskLogBto(saveEntity.getId(), message, null);
//            taskLogService.addLog(taskLogBto2);
            //发送阅知信息
            List<Integer> userIds = userPublicService.findOtherUser(userUtils.getCurrentUserId());
            MessageBto messageBto = new MessageBto(0,1,message,userIds,0);
            messageBto.setRecord(packingLibrary1.getId().toString());
            messageService.add(messageBto);
            //添加列装日志
            PackingLog packingLog = new PackingLog();
            packingLog.setRemark(message);
            packingLog.setPackingId(packingLibrary1.getId());
            packingLogService.add(packingLog);
        }
        PackingLibrary packingLibrary2 = addEntity(packingLibraryEntity);
        //添加列装日志
        PackingLog packingLog = new PackingLog();
        packingLog.setRemark("添加列装");
        packingLog.setPackingId(packingLibrary2.getId());
        packingLogService.add(packingLog);
        return true;

    }

    @Override
    public void getSortMap() {
            Map<String, Integer> map=new HashMap<>();
//        DeviceModelSort.mapModelSort = packingLibraryDao.findAllByIsRootAndPackingStatus(1,2).stream().collect(toMap(PackingLibrary::getModel,PackingLibrary::getShowOrder));
        packingLibraryDao.findAllByIsRootAndPackingStatus(1,2).forEach(packingLibrary -> {
            if (packingLibrary.getShowOrder()!=null) {
                map.put(packingLibrary.getModel(), packingLibrary.getShowOrder());
            }else {
                map.put(packingLibrary.getModel(), 9999);
            }
        });
        DeviceModelSort.mapModelSort=map;
    }

    @Override
    public List<PackingLibrary> findByParentId(Integer parentId) {
        return packingLibraryDao.findAllByPartParentId(parentId);
    }

//    @Override
//    public void bindingPacking(BindingPackingVo bindingPackingVo) {
//        Integer userId = userUtils.getCurrentUserId();
//        // 原始的列装 A1
//        PackingLibrary originPacking = bindingPackingVo.getOriginPacking();
//        // 要绑定的列装 B
//        PackingLibrary toPacking = bindingPackingVo.getToPacking();
//        // 如果原始的列装和要绑定的列装的型号不一致  则需要先修改其型号
//        if (!originPacking.getModel().equals(toPacking.getModel())) {
//            //查询原始列装下所有子节点也需要改变 包括自己
//            List<PackingLibrary> packingLibraries = packingLibraryDao.findAllByPartParentId(originPacking.getId());
//            //添加自己
//            packingLibraries.add(originPacking);
//            //先修改装备后修改列装
//            List<DeviceLibrary> deviceLibraryList = deviceLibraryService.findAllByModel(originPacking.getModel());
//            List<Integer> deviceIds = deviceLibraryList.stream().map(DeviceLibrary::getId).collect(Collectors.toList());
//            if (deviceLibraryList.size() > 0) {
//                //更新装备的型号和添加日志
//                deviceLibraryService.batchUpdateDevices(originPacking.getModel(), toPacking.getModel());
//                //存储日志
//                List<DeviceLog> logDtos;
//                String remarkDevice = "将原型号" + originPacking.getModel() + "修改型号为" + toPacking.getModel();
//                logDtos = deviceIds.stream().map(integer -> new DeviceLogDto(integer, remarkDevice, null, userId, null).toDo()).collect(Collectors.toList());
//                executor.execute(() -> {
//                    long start = System.currentTimeMillis();
//                    deviceLogService.saveAllLog(logDtos);
//                    log.info("saveAllLog时间：{}", System.currentTimeMillis() - start);
//                });
//                //更新列装
//                packingLibraries.forEach(packingLibrary -> {
//                    String remarkPacking = "由于绑定列装,需要绑定的列装型号和原列装型号不一致，将其修改为" + toPacking.getModel();
//                    PackingLog packingLog = new PackingLog();
//                    packingLog.setPackingId(packingLibrary.getId());
//                    packingLog.setRemark(remarkPacking);
//                    packingLogService.add(packingLog);
//                    packingLibrary.setModel(toPacking.getModel());
//                    addEntity(packingLibrary);
//                });
//            }
//        }
//        //修改父id
//        originPacking.setPartParentId(toPacking.getId());
//        addEntity(originPacking);
//    }

//    @Override
//    public void bindingPacking(BindingPackingVo bindingPackingVo) {
//        PackingLibrary originPacking = bindingPackingVo.getOriginPacking();
//        List<PackingLibrary> selectPacking = bindingPackingVo.getSelectPacking();
//
//        if (originPacking.getIsPart() == 0){
//            List<PackingLibrary> packingLibraries = new ArrayList<>();
//            //说明是附件
//            for (PackingLibrary packingLibrary : selectPacking) {
//                getChilds(packingLibraries, packingLibrary);
//            }
//            packingLibraries.stream().map(PackingLibrary::getIsPart)
//                    .filter(isPart -> isPart.equals(1))
//                    .findAny()
//                    .ifPresent(integer -> {
//                        throw new ApiException("附件不能绑定装备");
//                    });
//        }else {
//            //
//            selectPacking.forEach(packingLibrary -> {
//                packingLibrary.setPartParentId(originPacking.getId());
//                update(packingLibrary);
//            });
//        }
//
//
//    }

    @Override
    public void bindingPacking(BindingPackingVo bindingPackingVo) {
        //解绑的列装
        PackingLibrary originPacking = bindingPackingVo.getOriginPacking();
        //选择要绑定的列装
        PackingLibrary selectPacking = bindingPackingVo.getSelectPacking();
        //0 是装备目录 1 附件目录
        if (originPacking.getIsPart() == 0){
            //如果是装备目录   则只可以绑在列装目录下
            if (selectPacking.getIsPart()!=null){
                if(selectPacking.getIsPart() == 1){
                    throw new ApiException("附件下不可以绑定装备");
                }
            }
            // 1 是列装目录 0不是
            if (selectPacking.getIsRoot() == 0){
                throw new ApiException("装备只能绑定在列装目录下面");
            }
        }
        originPacking.setPartParentId(selectPacking.getId());
        PackingLog packingLog = new PackingLog();
        packingLog.setPackingId(originPacking.getId());
        if (selectPacking.getIsRoot() == 0){
            //不是目录  只能是附件
//            packingLog.setRemark("列装名称为"+originPacking.getName()+"与列装名称"+selectPacking.getName()+"进行绑定");
            packingLog.setRemark("附件:"+originPacking.getModel()+"  "+originPacking.getName()+"与装备:"
                    +selectPacking.getModel()+"  "+selectPacking.getName()+"进行绑定");
        }else {
            //是目录
//            packingLog.setRemark("列装名称为"+originPacking.getName()+"与列装目录型号"+selectPacking.getModel()+"进行绑定");
            if(originPacking.getIsPart() == 0){
                //0 装备  1 配件
                packingLog.setRemark("装备:"+originPacking.getModel()+"  "+originPacking.getName()+"与列装目录"+
                        selectPacking.getModel()+"进行绑定");
            }else {
                packingLog.setRemark("附件:"+originPacking.getModel()+"  "+originPacking.getName()+"与列装目录"+
                        selectPacking.getModel()+"进行绑定");
            }

        }
        packingLogService.add(packingLog);
        update(originPacking);
    }

    @Override
    public void relievePacking(PackingLibrary packingLibrary) {

        //获取列装对象的装备
        if (packingLibrary.getIsPart() == 1) {
            //说明是附件目录
            List<DeviceLibrary> deviceLibraries = deviceLibraryService.findAllByPackingId(packingLibrary.getId());
            if (deviceLibraries.size()>0){
                List<Integer> deviceIds = deviceLibraries.stream().map(DeviceLibrary::getId).collect(Collectors.toList());
                //将装备的父id全部置空
                Integer userId = userUtils.getCurrentUserId();
                List<DeviceLogDto> deviceLogDtos = new ArrayList<>();
                long l = System.currentTimeMillis();
                deviceLibraryService.updatePartParentId(deviceIds);
                log.info("更新父id时间为:{}",System.currentTimeMillis()-l);
                deviceLibraries.forEach(deviceLibrary -> {
                    DeviceLogDto deviceLogDto = new DeviceLogDto();
                    deviceLogDto.setDeviceId(deviceLibrary.getId());
                    deviceLogDto.setRemark("由于列装进行了解绑,装备也需要进行解绑");
                    deviceLogDto.setCreateUserId(userId);
                    deviceLogDtos.add(deviceLogDto);
                });
                executor.execute(()->{
                    deviceLogService.addAllLog(deviceLogDtos);
                });
            }
        }
        //修改列装
        packingLibrary.setPartParentId(null);
        PackingLog packingLog = new PackingLog();
        packingLog.setRemark("手动进行了列装解绑");
        packingLogService.add(packingLog);
        update(packingLibrary);
    }

    @Override
    public List<PackingLibrary> getAllSelectPacking(List<Integer> packingIds) {
        List<PackingLibrary> packingLibraryEntities =
                packingLibraryDao.findAll(getSelectSpecification22(new PackingLibrarySelectVo()));
        packingLibraryEntities.forEach(PackingLibrary::setConfigName);
        //查询列装
//        List<PackingLibrary> libraries = packingLibraryDao.findAllByIdIn(packingIds);
        packingLibraryEntities = packingLibraryEntities.stream().filter(packingLibrary ->
                !packingIds.contains(packingLibrary.getId())).collect(Collectors.toList());
//        packingLibraryEntities.removeAll(libraries);
        Map<Integer, PackingLibrary> nodeCollect =
                packingLibraryEntities.stream().collect(Collectors.toMap(PackingLibrary::getId, packingLibraryEntity -> packingLibraryEntity));
        return GetTreeUtils.parseTreeFromDown(
                packingLibraryEntities,
                PackingLibrary::getId,
                packingLibraryEntity -> Optional.ofNullable(nodeCollect.get(packingLibraryEntity.getPartParentId())),
                PackingLibrary::addChildNode
        ).stream().sorted(Comparator.comparing(PackingLibrary::getModel)).collect(Collectors.toList());
    }

    @Override
    public List<PackingLibrary> getAllSelectPacking(SelectPackingVo selectPackingVo) {
        List<PackingLibrary> packingLibraryEntities =
                packingLibraryDao.findAll(getSelectSpecification22(new PackingLibrarySelectVo()));
        packingLibraryEntities.forEach(PackingLibrary::setConfigName);
        //查询列装
        List<Integer> packingIds = selectPackingVo.getPackingIds();
//        List<PackingLibrary> libraries = packingLibraryDao.findAllByIdIn(packingIds);
        packingLibraryEntities = packingLibraryEntities.stream().filter(packingLibrary ->
                !packingIds.contains(packingLibrary.getId())).collect(Collectors.toList());

        if(selectPackingVo.getIsPart() == 0){
            //代表是装备  只显示目录
            packingLibraryEntities = packingLibraryEntities.stream().filter(packingLibrary -> packingLibrary.getIsRoot() == 1).collect(Collectors.toList());
            return packingLibraryEntities;
        }else {
            //附件  显示装备和目录
            packingLibraryEntities = packingLibraryEntities.stream()
                    .filter(packingLibrary -> packingLibrary.getIsRoot() == 1 || packingLibrary.getIsPart() == 0)
                    .collect(Collectors.toList());
        }
        Map<Integer, PackingLibrary> nodeCollect =
                packingLibraryEntities.stream().collect(Collectors.toMap(PackingLibrary::getId, packingLibraryEntity -> packingLibraryEntity));

        return GetTreeUtils.parseTreeFromDown(
                packingLibraryEntities,
                PackingLibrary::getId,
                packingLibraryEntity -> Optional.ofNullable(nodeCollect.get(packingLibraryEntity.getPartParentId())),
                PackingLibrary::addChildNode
        ).stream().sorted(Comparator.comparing(PackingLibrary::getModel)).collect(Collectors.toList());
    }

    @Override
    public List<PackingLibrary> findByIds(List<Integer> ids) {
        return packingLibraryDao.findAllByIdIn(ids);
    }

    private Specification<PackingLibrary> getSelectSpecification(PackingLibrarySelectVo packingLibrarySelectVo) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        Integer level = userUtils.getCurrentUnitLevel();
        if (level == 2) {
            predicateBuilder.in("invisibleRange", new Integer[]{2, 3});
        }
        if (level == 3) {
            predicateBuilder.eq("invisibleRange", 3);
        }
        if (packingLibrarySelectVo != null) {
            if (packingLibrarySelectVo.getContent() != null) {
                Class<PackingLibrary> packingLibraryEntityClass = PackingLibrary.class;
                Field[] declaredFields = packingLibraryEntityClass.getDeclaredFields();
                PredicateBuilder<PackingLibrary> p = Specifications.or();
                for (Field field : declaredFields) {
                    if (field.getType().equals(String.class) && field.getAnnotation(Transient.class) == null) {
                        p.like(field.getName(), "%" + packingLibrarySelectVo.getContent() + "%");
                    }
                }
                predicateBuilder.predicate(p.build());
            }
            if (packingLibrarySelectVo.getStartTime() != null) {
                predicateBuilder.gt("createTime", packingLibrarySelectVo.getStartTime());
            }
            if (packingLibrarySelectVo.getEndTime() != null) {
                predicateBuilder.lt("updateTime", packingLibrarySelectVo.getEndTime());
            }
            if (packingLibrarySelectVo.getModel() != null) {
                predicateBuilder.eq("model", packingLibrarySelectVo.getModel());
            }
            if (packingLibrarySelectVo.getType() != null) {
                predicateBuilder.eq("type", packingLibrarySelectVo.getType());
            }
            if (packingLibrarySelectVo.getSecretLevel() != null) {
                predicateBuilder.eq("secretLevel", packingLibrarySelectVo.getSecretLevel());
            }
            if (packingLibrarySelectVo.getInvisibleRange() != null) {
                predicateBuilder.eq("invisibleRange", packingLibrarySelectVo.getInvisibleRange());
            }
            if (packingLibrarySelectVo.getName() != null) {
                predicateBuilder.eq("name", packingLibrarySelectVo.getName());
            }
        }
        predicateBuilder.eq("packingStatus", 2);
        predicateBuilder.eq("isRoot",0);
        return predicateBuilder.build();
    }
    private Specification<PackingLibrary> getSelectSpecification22(PackingLibrarySelectVo packingLibrarySelectVo) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        Integer level = userUtils.getCurrentUnitLevel();
        if (level == 2) {
            predicateBuilder.in("invisibleRange", new Integer[]{2, 3});
        }
        if (level == 3) {
            predicateBuilder.eq("invisibleRange", 3);
        }
        if (packingLibrarySelectVo != null) {
            if (packingLibrarySelectVo.getContent() != null) {
                Class<PackingLibrary> packingLibraryEntityClass = PackingLibrary.class;
                Field[] declaredFields = packingLibraryEntityClass.getDeclaredFields();
                PredicateBuilder<PackingLibrary> p = Specifications.or();
                for (Field field : declaredFields) {
                    if (field.getType().equals(String.class) && field.getAnnotation(Transient.class) == null) {
                        p.like(field.getName(), "%" + packingLibrarySelectVo.getContent() + "%");
                    }
                }
                predicateBuilder.predicate(p.build());
            }
            if (packingLibrarySelectVo.getStartTime() != null) {
                predicateBuilder.gt("createTime", packingLibrarySelectVo.getStartTime());
            }
            if (packingLibrarySelectVo.getEndTime() != null) {
                predicateBuilder.lt("updateTime", packingLibrarySelectVo.getEndTime());
            }
            if (packingLibrarySelectVo.getModel() != null) {
                predicateBuilder.eq("model", packingLibrarySelectVo.getModel());
            }
            if (packingLibrarySelectVo.getType() != null) {
                predicateBuilder.eq("type", packingLibrarySelectVo.getType());
            }
            if (packingLibrarySelectVo.getSecretLevel() != null) {
                predicateBuilder.eq("secretLevel", packingLibrarySelectVo.getSecretLevel());
            }
            if (packingLibrarySelectVo.getInvisibleRange() != null) {
                predicateBuilder.eq("invisibleRange", packingLibrarySelectVo.getInvisibleRange());
            }
            if (packingLibrarySelectVo.getName() != null) {
                predicateBuilder.eq("name", packingLibrarySelectVo.getName());
            }
        }
        predicateBuilder.eq("packingStatus", 2);
//        predicateBuilder.eq("isRoot",0);
        predicateBuilder.in("isRoot",new Integer[]{0,1});
        return predicateBuilder.build();
    }

    private Specification<PackingLibrary> getSelectSpecification2(PackingLibrarySelectVo packingLibrarySelectVo) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        Integer level = userUtils.getCurrentUnitLevel();
        if (level == 2) {
            predicateBuilder.in("invisibleRange", new Integer[]{2, 3});
        }
        if (level == 3) {
            predicateBuilder.eq("invisibleRange", 3);
        }
        if (packingLibrarySelectVo != null) {
            if (packingLibrarySelectVo.getContent() != null) {
                Class<PackingLibrary> packingLibraryEntityClass = PackingLibrary.class;
                Field[] declaredFields = packingLibraryEntityClass.getDeclaredFields();
                PredicateBuilder<PackingLibrary> p = Specifications.or();
                for (Field field : declaredFields) {
                    if (field.getType().equals(String.class) && field.getAnnotation(Transient.class) == null) {
                        p.like(field.getName(), "%" + packingLibrarySelectVo.getContent() + "%");
                    }
                }
                predicateBuilder.predicate(p.build());
            }
            if (packingLibrarySelectVo.getStartTime() != null) {
                predicateBuilder.gt("createTime", packingLibrarySelectVo.getStartTime());
            }
            if (packingLibrarySelectVo.getEndTime() != null) {
                predicateBuilder.lt("updateTime", packingLibrarySelectVo.getEndTime());
            }
            if (packingLibrarySelectVo.getModel() != null) {
                predicateBuilder.eq("model", packingLibrarySelectVo.getModel());
            }
            if (packingLibrarySelectVo.getName() != null) {
                predicateBuilder.eq("name", packingLibrarySelectVo.getName());
//                predicateBuilder.like("name", "%"+packingLibrarySelectVo.getName()+"%");
            }
            if (packingLibrarySelectVo.getType() != null) {
                predicateBuilder.eq("type", packingLibrarySelectVo.getType());
            }
            if (packingLibrarySelectVo.getSecretLevel() != null) {
                predicateBuilder.eq("secretLevel", packingLibrarySelectVo.getSecretLevel());
            }
            if (packingLibrarySelectVo.getInvisibleRange() != null) {
                predicateBuilder.eq("invisibleRange", packingLibrarySelectVo.getInvisibleRange());
            }
            if (packingLibrarySelectVo.getPackingStatus()!=null){
                predicateBuilder.eq("packingStatus", packingLibrarySelectVo.getPackingStatus());
            }
            else {
                predicateBuilder.eq("packingStatus", 3);
            }
//            predicateBuilder.eq(packingLibrarySelectVo.getPackingStatus()!= null,"packingStatus",packingLibrarySelectVo.getPackingStatus());
        }
//        predicateBuilder.eq("isPart", 0);
//        predicateBuilder.in("isRoot",new Integer[]{0,1});
        return predicateBuilder.build();
    }

    private Specification<PackingLibrary> getSelectSpecification3(Integer id) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("packingStatus", 2);
        predicateBuilder.eq("isPart", 1);
        predicateBuilder.eq("partParentId", id);
        return predicateBuilder.build();
    }

    private Specification<PackingLibrary> getSelectSpecification4(Integer id) {
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("packingStatus", 3);
        predicateBuilder.eq("isPart", 1);
        predicateBuilder.eq("partParentId", id);
        return predicateBuilder.build();
    }

    private Specification<PackingLibrary> getSelectSpecification5(PackingLibrarySelectVo packingLibrarySelectVo) {
        Integer level = userUtils.getCurrentUnitLevel();
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        if (level == 2) {
            predicateBuilder.in("invisibleRange", new Integer[]{2, 3});
        }
        if (level == 3) {
            predicateBuilder.eq("invisibleRange", 3);
        }
        if (packingLibrarySelectVo != null) {
            if (packingLibrarySelectVo.getContent() != null) {
                Class<PackingLibrary> packingLibraryEntityClass = PackingLibrary.class;
                Field[] declaredFields = packingLibraryEntityClass.getDeclaredFields();
                PredicateBuilder<PackingLibrary> p = Specifications.or();
                for (Field field : declaredFields) {
                    if (field.getType().equals(String.class) && field.getAnnotation(Transient.class) == null) {
                        p.like(field.getName(), "%" + packingLibrarySelectVo.getContent() + "%");
                    }
                }
                predicateBuilder.predicate(p.build());
            }
            if (packingLibrarySelectVo.getStartTime() != null) {
                predicateBuilder.gt("createTime", packingLibrarySelectVo.getStartTime());
            }
            if (packingLibrarySelectVo.getEndTime() != null) {
                predicateBuilder.lt("updateTime", packingLibrarySelectVo.getEndTime());
            }
            if (packingLibrarySelectVo.getModel() != null) {
                predicateBuilder.eq("model", packingLibrarySelectVo.getModel());
            }
            if (packingLibrarySelectVo.getType() != null) {
                predicateBuilder.eq("type", packingLibrarySelectVo.getType());
            }
            if (packingLibrarySelectVo.getSecretLevel() != null) {
                predicateBuilder.eq("secretLevel", packingLibrarySelectVo.getSecretLevel());
            }
            if (packingLibrarySelectVo.getInvisibleRange() != null) {
                predicateBuilder.eq("invisibleRange", packingLibrarySelectVo.getInvisibleRange());
            }
            if (packingLibrarySelectVo.getName() != null) {
                predicateBuilder.eq("name", packingLibrarySelectVo.getName());
            }
        }
        predicateBuilder.eq("packingStatus", 2);
        predicateBuilder.eq("isPart", 0);
        return predicateBuilder.build();
    }

    private Specification<PackingLibrary> getSelectSpecification6(){
        Integer level = userUtils.getCurrentUnitLevel();
        PredicateBuilder<PackingLibrary> predicateBuilder = Specifications.and();
        if (level == 2) {
            predicateBuilder.in("invisibleRange", new Integer[]{2, 3});
        }
        if (level == 3) {
            predicateBuilder.eq("invisibleRange", 3);
        }
        predicateBuilder.eq("packingStatus", 2);
        return predicateBuilder.build();
    }

    private List<PackingLibrary> findByModelAndIsRoot(List<String> models){
        return packingLibraryDao.findAllByModelInAndIsRootAndPackingStatus(models,1,2);
    }

    /**
     * 得到所有的子
     * @param
     * @return
     */
    public List<PackingLibrary> getChilds(List<PackingLibrary> packingLibraries,PackingLibrary packingLibrary){

            packingLibraries.add(packingLibrary);
            List<PackingLibrary> childs = packingLibrary.getChilds();
            if (childs != null){
                childs.forEach(packingLibrary1 -> {
                    List<PackingLibrary> childs1 = getChilds(packingLibraries,packingLibrary1);
                    packingLibraries.addAll(childs1);
                });
            }

        return packingLibraries;
    }

    //递归取出最大目录
    public PackingLibrary getPackingLibrary(PackingLibrary packingLibrary) {
        Integer partParentId = packingLibrary.getPartParentId();
        PackingLibrary one = getOne(partParentId);
        if (one.getIsRoot() == 0) {
            return getPackingLibrary(one);
        } else {
            return packingLibrary;
        }
    }


}
