package com.persagy.dmp.rwd.digital.service.calstrategy;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.persagy.dmp.basic.dto.RelationCalRuleDTO;
import com.persagy.dmp.digital.entity.ObjectRelation;
import com.persagy.dmp.rwd.basic.utils.DigitalCommonUtils;
import com.persagy.dmp.rwd.basic.utils.GeoToolsUtil;
import com.persagy.dmp.rwd.digital.dao.ObjectRelationMapper;
import com.persagy.dmp.rwd.digital.domain.CalculatingDTO;
import com.persagy.dmp.rwd.digital.service.CalculateService;
import com.persagy.dmp.rwd.digital.service.IObjectRelationService;
import com.persagy.dmp.rwd.digital.utils.ObjectDigitalCriteriaHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/***
 * Description: 楼层贯通关系计算
 * @author : lijie
 * @date :2021/10/9 16:26
 * Update By lijie 2021/10/9 16:26
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ShThroughShRelCalculateServiceImpl implements CalculateService {

    private final IObjectRelationService objectRelationService;
    private final ObjectRelationMapper objectRelationMapper;


    /***
     * Description: 楼层贯通关系计算
     * @param calRule : 计算规则
     * @param calculatingDTO : 请求参数
     * @return : void
     * @author : lijie
     * @date :2021/10/9 16:26
     * Update By lijie 2021/10/9 16:26
     */
    @Override
    public void calculateRelation(RelationCalRuleDTO calRule, CalculatingDTO calculatingDTO) {
        // 1.根据图类型,边类型查询符合条件空间与竖井关系对应的竖井与空间对应关系
        List<ObjectRelation> objectRelations = objectRelationMapper.queryArchSubsetShToSp(calculatingDTO);
        if (CollUtil.isEmpty(objectRelations)){
            return;
        }
        // 2.根据空间坐标计算有相交的竖井即存在连通关系
        // 2.1 获得{空间id:空间坐标}的映射
        Map<String, ArrayNode> spaceMap = objectRelations.stream()
                .collect(Collectors.toMap(ObjectRelation::getObjTo, ObjectRelation::getOutLines, (k1, k2) -> k1));
        // 2.2 获得{竖井id:[空间id,空间id]}的映射
        Map<String, Set<String>> shaftSpaceIdMap = new HashMap<>();
        objectRelations.forEach(relation->{
                    Set<String> spaceIds = shaftSpaceIdMap.getOrDefault(relation.getObjFrom(), new HashSet<>());
                    spaceIds.add(relation.getObjTo());
                    shaftSpaceIdMap.put(relation.getObjFrom(),spaceIds);
                });
        // 2.3 根据空间的坐标是否相交确定竖井的连通性
        List<ObjectRelation> resultList = new ArrayList<>();
        Set<Map.Entry<String, Set<String>>> entries = shaftSpaceIdMap.entrySet();
        for (Map.Entry<String, Set<String>> entry : entries) {
            for (Map.Entry<String, Set<String>> otherEntry : entries) {
                if (entry.getKey().equals(otherEntry.getKey())){
                    continue;
                }
                String shaftId = entry.getKey();
                String otherShaftId = otherEntry.getKey();
                Set<String> spaceIds = entry.getValue();
                Set<String> otherSpaceIds = otherEntry.getValue();
                Collection<String> intersection = CollUtil.intersection(spaceIds, otherSpaceIds);
                if (intersection.size()>0){
                    continue;
                }
                if (isVerticallyOverlap(spaceIds,otherSpaceIds,spaceMap)){
                    // 空间有相交的空间,说明两者竖井是连通的
                    ObjectRelation objectRelation = new ObjectRelation();
                    objectRelation.setGroupCode(calculatingDTO.getGroupCode());
                    objectRelation.setProjectId(calculatingDTO.getProjectId());
                    objectRelation.setGraphCode(calculatingDTO.getGraphCode());
                    objectRelation.setRelCode(calculatingDTO.getRelCode());
                    objectRelation.setRelValue(calculatingDTO.getRelValue());
                    objectRelation.setObjFrom(shaftId);
                    objectRelation.setObjTo(otherShaftId);
                    resultList.add(objectRelation);
                }
            }
        }
        if (CollUtil.isNotEmpty(resultList)){
            // 3.根据图类型编码,边类型编码,relValue,项目id,集团编码删除关系
            deleteRelDataByCondition(calculatingDTO);
            // 4.新增关系
            objectRelationService.save(resultList);
        }
    }
    /***
     * Description: 判断两组空间是否存在连通性
     * @param spaceIds : 空间id数组
     * @param otherSpaceIds : 另一组空间id数组
     * @param spaceMap : 空间id映射
     * @return : boolean
     * @author : lijie
     * @date :2021/10/11 14:13
     * Update By lijie 2021/10/11 14:13
     */
    private Boolean isVerticallyOverlap(Set<String> spaceIds, Set<String> otherSpaceIds,
                                        Map<String, ArrayNode> spaceMap) {
        for (String spaceId : spaceIds) {
            for (String otherSpaceId : otherSpaceIds) {
                if (GeoToolsUtil.isPolyInPoly(spaceMap.get(spaceId),spaceMap.get(otherSpaceId))){
                    return true;
                }
            }
        }
        return false;
    }

    /***
     * Description: 根据请求参数和id集合删除关系
     * @param calculatingDTO : 请求参数
     * @return : void
     * @author : lijie
     * @date :2021/9/11 16:13
     * Update By lijie 2021/9/11 16:13
     */
    private void deleteRelDataByCondition(CalculatingDTO calculatingDTO) {
        QueryWrapper<ObjectRelation> queryWrapper = ObjectDigitalCriteriaHelper.createCommonQueryWrapper(null,calculatingDTO);
        queryWrapper.eq(StrUtil.toUnderlineCase(ObjectRelation.GRAPH_CODE_HUM),calculatingDTO.getGraphCode());
        queryWrapper.eq(StrUtil.toUnderlineCase(ObjectRelation.REL_CODE_HUM),calculatingDTO.getRelCode());
        objectRelationService.delete(queryWrapper);
    }
}
