package com.persagy.adm.server.backstage.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.adm.server.algorithm.entity.AdmModelFile;
import com.persagy.adm.server.algorithm.service.AdmModelService;
import com.persagy.adm.server.backstage.constant.DataHandlerEnum;
import com.persagy.adm.server.backstage.domain.AdmAnalysisModel;
import com.persagy.adm.server.backstage.service.DataHandlerService;
import com.persagy.dmp.basic.model.QueryCriteria;
import com.persagy.dmp.common.constant.CommonConstant;
import com.persagy.dmp.common.helper.SpringHelper;
import com.persagy.dmp.digital.client.DigitalObjectFacade;
import com.persagy.dmp.digital.client.DigitalRelationFacade;
import com.persagy.dmp.digital.entity.ObjectRelation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 数据处理类
 * @author : lijie
 * Update By 2022/1/21 16:24
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class AdmDataHandleServiceImpl extends AdmAnalysisServiceBase {
    /**元素集合key*/
    private final static String ELEMENTS="Elements";
    /**项目id的key*/
    private final static String PROJECT_ID="ProjectId";
    /**楼层名称的key*/
    private final static String PLAN_NAME="PlanName";

    private final AdmModelService admModelService;

    @Override
    protected void analysisInternal(AdmAnalysisModel model) {
        JSONObject currentAdmModelObj = model.getCurrentAdmModelObj();
        if (null==currentAdmModelObj){
            return;
        }
        // 1.根据当前楼层id查询bimId的对象:bimId生成规则:项目id+楼层id+:+sourceId
        AdmModelFile currentModelFile = model.getCurrentModelFile();
        if (null==currentModelFile){
            return;
        }
        String bimIdPre = StrUtil.join(StrUtil.EMPTY, currentModelFile.getProjectId(), currentModelFile.getFloorId());
        Map<String, ObjectNode> objectNodeMap = admModelService
                .queryObjectDigitalsByBimIdPre(currentModelFile.getGroupCode(), bimIdPre);
        // 2.解析数据为物理世界对象
        JSONObject elements = currentAdmModelObj.getJSONObject(ELEMENTS);
        String planName = currentAdmModelObj.getString(PLAN_NAME);
        Set<String> keySet = elements.keySet();
        for (String key : keySet) {
            JSONArray objects = elements.getJSONArray(key);
            DataHandlerEnum load = DataHandlerEnum.load(key);
            DataHandlerService handlerService = SpringHelper.getBean(load.getName(), DataHandlerService.class);
            handlerService.handleData(objectNodeMap,model,objects,key,planName);
        }
        List<ObjectNode> needAddObjects = model.getNeedAddObjects();
        List<ObjectNode> needUpdateObjects = model.getNeedUpdateObjects();
        Set<String> needDeleteObjectIds = model.getNeedDeleteObjectIds();
        Set<String> needDeleteRelationObjIds = model.getNeedDeleteRelationObjIds();
        List<ObjectRelation> needAddRelations = model.getNeedAddRelations();
        if (CollUtil.isNotEmpty(needAddObjects)){
            DigitalObjectFacade.create(currentModelFile.getGroupCode(),currentModelFile.getProjectId(),
                    CommonConstant.DEFAULT_ID,CommonConstant.DEFAULT_ID,needAddObjects);
        }
        if (CollUtil.isNotEmpty(needUpdateObjects)){
            DigitalObjectFacade.update(currentModelFile.getGroupCode(),currentModelFile.getProjectId(),
                    CommonConstant.DEFAULT_ID,CommonConstant.DEFAULT_ID,needUpdateObjects);
        }
        if (CollUtil.isNotEmpty(needDeleteObjectIds)){
            DigitalObjectFacade.delete(currentModelFile.getGroupCode(),currentModelFile.getProjectId(),
                    CommonConstant.DEFAULT_ID,CommonConstant.DEFAULT_ID,CollUtil.newArrayList(needDeleteObjectIds));
        }
        if (CollUtil.isNotEmpty(needDeleteRelationObjIds)){
            QueryCriteria criteria = new QueryCriteria();
            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
            ObjectNode objectNode = objectMapper.createObjectNode();
            objectNode.putPOJO(ObjectRelation.OBJ_FROM_HUM,needDeleteRelationObjIds);
            objectNode.putPOJO(ObjectRelation.GRAPH_CODE_HUM,model.getNeedDeleteRelationGraphCodes());
            objectNode.putPOJO(ObjectRelation.REL_CODE_HUM,model.getNeedDeleteRelationRelCodes());
            criteria.setCriteria(objectNode);
            DigitalRelationFacade.deleteByCriteria(currentModelFile.getGroupCode(),currentModelFile.getProjectId(),
                    CommonConstant.DEFAULT_ID,CommonConstant.DEFAULT_ID,criteria);
            objectNode.remove(ObjectRelation.OBJ_FROM_HUM);
            objectNode.putPOJO(ObjectRelation.OBJ_TO_HUM,needDeleteRelationObjIds);
            DigitalRelationFacade.deleteByCriteria(currentModelFile.getGroupCode(),currentModelFile.getProjectId(),
                    CommonConstant.DEFAULT_ID,CommonConstant.DEFAULT_ID,criteria);
        }
        if (CollUtil.isNotEmpty(needAddRelations)){
            DigitalRelationFacade.create(currentModelFile.getGroupCode(),currentModelFile.getProjectId(),
                    CommonConstant.DEFAULT_ID,CommonConstant.DEFAULT_ID,needAddRelations);
        }
    }

    @Override
    protected void afterAnalysis(AdmAnalysisModel model) {
        model.setNeedDeleteRelationRelCodes(null);
        model.setNeedDeleteRelationGraphCodes(null);
        model.setNeedDeleteRelationObjIds(null);
        model.setNeedAddRelations(null);
        model.setNeedUpdateObjects(null);
        model.setNeedDeleteObjectIds(null);
        model.setNeedAddObjects(null);
        model.setCurrentAdmModelObj(null);
        model.setCurrentModelFile(null);
        model.setCurrentFloor(null);
    }

    @Override
    protected void afterAnalysisException(AdmAnalysisModel model,String errorMessage) {
        AdmModelFile currentModelFile = model.getCurrentModelFile();
        currentModelFile.setSyncErrorMsg(errorMessage);
        currentModelFile.setSyncRetryTimes(ObjectUtil
                .isNull(currentModelFile.getSyncRetryTimes())?1:currentModelFile.getSyncRetryTimes()+1);
    }
}
