package com.sagacloud.utils.objects;
/*
 * Author: Jxing
 * Create Time: 2018/10/15
 */

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sagacloud.dict.RelStaticInfo;
import com.sagacloud.utils.CommonUtil;
import com.sagacloud.utils.Const;
import com.sagacloud.utils.relationUtils.RelationUtil;
import com.sagacloud.utils.tables.HBaseTable;
import com.sagacloud.utils.tables.ObjectTable;
import com.sagacloud.utils.tables.RelTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.Set;

public class AffectedBusinessSpace implements Runnable {
    String iSpaceId;
    String pjId;
    String graphId;
    private static final Logger log = LoggerFactory.getLogger(AffectedBusinessSpace.class);
    /**
     * 检查删除的元空间是否影响了业务空间.(影响判定: 如果删除了该元空间则某个业务空间下没有任何元空间,
     * 那么这个业务空间就受到了影响, 需要通知)
     * @param pjId
     * @param iSpaceId
     */
    public AffectedBusinessSpace(String pjId, String iSpaceId, String graphId){
        this.iSpaceId = iSpaceId;
        this.pjId = pjId;
        this.graphId = graphId;
    }
    @Override
    public void run() {
        // 先查询所有受到影响的业务空间id
        String time = CommonUtil.getTime();
        try{
            if(graphId == null || !graphId.startsWith("GtElementSptoSpace")){
                graphId = RelationUtil.getGraphInstance(pjId, "ElementSptoSpace", time, true);
                if(graphId == null) {
                    throw new Exception("删除元空间后, 检查受影响的业务空间时: 图实例获取失败." + iSpaceId);
                }
            }
            JSONArray arr = generateQueryRelBtwObjectsCriteria();
            if(arr == null)
                throw new Exception("删除元空间后, 检查受影响的业务空间时: 未获取到必要的数据字典信息" + iSpaceId);
            JSONObject result = CommonUtil.combine_query(HBaseTable.rel_btw_objs, arr);
            if(!result.getString("Result").equals("success")){
                throw new Exception("删除元空间后, 检查受影响的业务空间时: 查询关系失败" + iSpaceId);
            }
            JSONArray content = result.getJSONArray("Content");
            // 获取所有的业务空间id.
            Set<String> businessIdSet = new HashSet<>();
            for(int i = 0; i < content.size(); ++i){
                JSONObject singleRow = content.getJSONObject(i);
                try {
                    if (!businessIdSet.contains(singleRow.getString(RelTable.KEY_TO_OBJ_ID))){
                        businessIdSet.add(singleRow.getString(RelTable.KEY_TO_OBJ_ID));
                    }
                }catch (Exception ignored){}
            }
            // 删除元空间的关系
            // 如果没有业务空间, 则表示没有可以删除的关系, 也没有需要通知的业务空间
            if(businessIdSet.size() == 0)
                return;
            result = CommonUtil.combine_delete(HBaseTable.rel_btw_objs, arr);
            if(!result.getString("Result").equals("success")){
                throw new Exception("删除元空间后, 检查受影响的业务空间时: 删除元空间与业务空间的关系失败" + iSpaceId);
            }
            // 查询是否业务空间下已经没有元空间, 若没有元空间, 则添加到通知表中
            JSONArray queryCriteria = generateQueryRelBtwObjectsCriteria(businessIdSet);
            JSONObject countResult = CommonUtil.getCount(true, HBaseTable.rel_btw_objs, queryCriteria);
            content = countResult.getJSONArray("Content");
            int i = 0;
            Set<String> affectedSpace = new HashSet<>();
            for(String businessUUID : businessIdSet){
                int count = 0;
                for(int begin = RelStaticInfo.globalGraphRelSetMap.get("ElementSptoSpace").size() * i; begin < content.size(); ++begin){
                    JSONObject singleCount = content.getJSONObject(begin);
                    count += singleCount.getLongValue("Count");
                }
                if(count == 0){
                    if(!affectedSpace.contains(businessUUID)){
                        affectedSpace.add(businessUUID);
                    }
                }
                ++i;
            }
            if(affectedSpace.size() == 0)
                return;
            // 插入到通知表中
            JSONArray insertObjects = new JSONArray();
            for(String businessUUID : affectedSpace){
                JSONObject obj = new JSONObject();
                obj.put(ObjectTable.KEY_PJ_ID, pjId);
                obj.put(ObjectTable.KEY_OBJ_TYPE, Const.OBJ_TYPE_SPACE);
                obj.put(ObjectTable.KEY_OBJ_ID, businessUUID);
                obj.put("atime", time);
                obj.put("note", iSpaceId);
                insertObjects.add(obj);
            }
            CommonUtil.insert(true, HBaseTable.business_space_notice, insertObjects);
        }catch (Exception ex){
            log.error(ex.getMessage());
        }
    }

    /**
     * 生成按照业务空间查询的条件
     * @param businessIdSet 业务空间的id(仅uuid部分)
     * @return 返回查询条件
     */
    private JSONArray generateQueryRelBtwObjectsCriteria(Set<String> businessIdSet) {
        JSONArray arr = new JSONArray();
        Set<String> relTypeSet = RelStaticInfo.globalGraphRelSetMap.get("ElementSptoSpace");
        for(String businessId : businessIdSet) {
            for (String type : relTypeSet) {
                JSONObject singleCriteria = new JSONObject();
                singleCriteria.put(RelTable.KEY_PJ_ID, pjId);
                singleCriteria.put(RelTable.KEY_GRAPH_ID, graphId);
                singleCriteria.put(RelTable.KEY_REL_TYPE, type);
                singleCriteria.put(RelTable.KEY_TO_OBJ_TYPE, Const.OBJ_TYPE_SPACE);
                singleCriteria.put(RelTable.KEY_TO_OBJ_ID, businessId);
                arr.add(singleCriteria);
            }
        }
        return arr;
    }

    private JSONArray generateQueryRelBtwObjectsCriteria() {
        JSONArray arr = new JSONArray();
        Set<String> relTypeSet = RelStaticInfo.globalGraphRelSetMap.get("ElementSptoSpace");
        for(String type : relTypeSet){
            JSONObject singleCriteria = new JSONObject();
            singleCriteria.put(RelTable.KEY_PJ_ID, pjId);
            singleCriteria.put(RelTable.KEY_GRAPH_ID, graphId);
            singleCriteria.put(RelTable.KEY_REL_TYPE, type);
            singleCriteria.put(RelTable.KEY_FROM_OBJ_TYPE, Const.OBJ_TYPE_ISPACE);
            singleCriteria.put(RelTable.KEY_FROM_OBJ_ID, iSpaceId.substring(12));
            arr.add(singleCriteria);
        }
        if(arr.size() == 0)
            return null;
        return arr;
    }
}
