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.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.persagy.dmp.basic.dto.RelationCalRuleDTO;
import com.persagy.dmp.digital.entity.ObjectDigital;
import com.persagy.dmp.digital.entity.ObjectRelation;
import com.persagy.dmp.rwd.basic.constant.DigitalObjectType;
import com.persagy.dmp.rwd.basic.utils.DigitalCommonUtils;
import com.persagy.dmp.rwd.basic.utils.GeoToolsUtil;
import com.persagy.dmp.rwd.digital.dao.ObjectDigitalMapper;
import com.persagy.dmp.rwd.digital.domain.CalculatingDTO;
import com.persagy.dmp.rwd.digital.service.CalculateService;
import com.persagy.dmp.rwd.digital.service.IObjectDigitalService;
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.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/***
 * Description: 根据坐标计算关系的策略类
 * @author : lijie
 * @date :2021/9/8 17:02
 * Update By lijie 2021/9/8 17:02
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class EqToSpCalculateServiceImpl implements CalculateService {

    private final IObjectDigitalService objectDigitalService;
    private final ObjectDigitalMapper objectDigitalMapper;
    private final IObjectRelationService objectRelationService;

    /***
     * Description: 根据坐标计算关系
     * @param calRule : 计算规则
     * @param calculatingDTO : 参数
     * @return : void
     * @author : lijie
     * @date :2021/9/8 17:14
     * Update By lijie 2021/9/8 17:14
     */
    @Override
    public void calculateRelation(RelationCalRuleDTO calRule, CalculatingDTO calculatingDTO) {
        // 1.先根据项目id查询项目下的所有项目
        List<ObjectDigital> floors = queryFloorsByProjectId(calculatingDTO.getGroupCode(),calculatingDTO.getProjectId());
        if (CollUtil.isEmpty(floors)){
            return;
        }
        // 2.根据各个楼层分别进行关系计算
        for (ObjectDigital floor : floors) {
            // 2.1 根据项目id和楼层id查询设备列表
            List<ObjectDigital> equipments = objectDigitalMapper
                    .queryEquipBimLocationsByProjectIdAndFloorId(calculatingDTO.getGroupCode(),
                            calculatingDTO.getProjectId(),floor.getId());
            if (CollUtil.isEmpty(equipments)){
                continue;
            }
            List<ObjectDigital> spaces =objectDigitalMapper.querySpacesByProjectIdAndFloorId(calculatingDTO.getGroupCode(),
                    calculatingDTO.getProjectId(),floor.getId());
            if (CollUtil.isEmpty(spaces)){
                continue;
            }
            List<ObjectRelation> insertRels = new ArrayList<>();
            for (ObjectDigital equipment : equipments) {
                for (ObjectDigital space : spaces) {
                    if (GeoToolsUtil.isPointInPoly(equipment.getBimLocation(),space.getOutLines())){
                        ObjectRelation objectRelation = new ObjectRelation();
                        objectRelation.setGroupCode(calculatingDTO.getGroupCode());
                        objectRelation.setProjectId(calculatingDTO.getProjectId());
                        objectRelation.setGraphCode(calculatingDTO.getGraphCode());
                        objectRelation.setRelCode(calculatingDTO.getRelCode());
                        objectRelation.setRelValue(space.getClassCode());
                        objectRelation.setObjFrom(equipment.getId());
                        objectRelation.setObjTo(space.getId());
                        insertRels.add(objectRelation);
                    }
                }
            }
            if (CollUtil.isNotEmpty(insertRels)){
                deleteRelDataByCondition(calculatingDTO,insertRels.stream().map(ObjectRelation::getObjFrom).collect(Collectors.toSet()),
                        insertRels.stream().map(ObjectRelation::getObjTo).collect(Collectors.toSet()),
                        insertRels.stream().map(ObjectRelation::getRelValue).collect(Collectors.toSet()));
                objectRelationService.save(insertRels);
            }
        }

    }
    /***
     * Description: 根据集团编码和项目id查询项目下的楼层
     * @param groupCode : 集团编码
     * @param projectId : 项目id
     * @return : java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>
     * @author : lijie
     * @date :2021/11/24 10:06
     * Update By lijie 2021/11/24 10:06
     */
    private List<ObjectDigital> queryFloorsByProjectId(String groupCode, String projectId) {
        if (StrUtil.isBlank(projectId)){
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ObjectDigital> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ObjectDigital::getValid,Boolean.TRUE);
        queryWrapper.eq(ObjectDigital::getGroupCode,groupCode);
        queryWrapper.eq(ObjectDigital::getProjectId,projectId);
        queryWrapper.eq(ObjectDigital::getObjType, DigitalObjectType.FLOOR.getIndex());
        return objectDigitalService.list(queryWrapper);
    }

    /***
     * Description: 根据请求参数和id集合删除关系
     * @param calculatingDTO : 请求参数
     * @param fromIds : 来源id集合
     * @param toIds : 去向id集合
     * @return : void
     * @author : lijie
     * @date :2021/9/11 16:13
     * Update By lijie 2021/9/11 16:13
     */
    private void deleteRelDataByCondition(CalculatingDTO calculatingDTO, Set<String> fromIds, Set<String> toIds,
             Set<String> relVals) {
        QueryWrapper<ObjectRelation> queryWrapper = ObjectDigitalCriteriaHelper
                .createCommonQueryWrapper(CollUtil.newHashSet(),calculatingDTO);
        queryWrapper.eq(StrUtil.toUnderlineCase(ObjectRelation.GRAPH_CODE_HUM),calculatingDTO.getGraphCode());
        queryWrapper.eq(StrUtil.toUnderlineCase(ObjectRelation.REL_CODE_HUM),calculatingDTO.getRelCode());
        queryWrapper.in(CollUtil.isNotEmpty(relVals),StrUtil.toUnderlineCase(ObjectRelation.REL_VALUE_HUM),relVals);
        queryWrapper.and(CollUtil.isNotEmpty(fromIds) || CollUtil.isNotEmpty(toIds),wrapper->{
            wrapper.or(CollUtil.isNotEmpty(fromIds),subWapper->subWapper.in(ObjectRelation.OBJ_FROM,fromIds));
            wrapper.or(CollUtil.isNotEmpty(toIds),subWapper->subWapper.in(ObjectRelation.OBJ_TO,toIds));
        });
        objectRelationService.delete(queryWrapper);
    }
}
