package com.sagacloud.search;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sagacloud.cache.EhCaches;
import com.sagacloud.dict.EqStaticInfo;
import com.sagacloud.search.infoPoint.InformationPoint;
import com.sagacloud.search.objs.*;
import com.sagacloud.utils.CommonUtil;
import com.sagacloud.utils.OssUtils;
import com.sagacloud.utils.ZillionAgentProvider;
import com.sagacloud.utils.tables.ObjInfosTable;
import com.sagacloud.utils.tables.ObjectTable;
import com.sagacloud.utils.tables.RelBtwGraphPeriodFields;
import com.sagacloud.utils.tables.RelTable;
import de.jkeylockmanager.manager.KeyLockManager;
import de.jkeylockmanager.manager.KeyLockManagers;
import org.ehcache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * Created by wo on 8/22/17.
 */
public class AllObjs {
    private static final String LOCAL_NAME = "LocalName";

    private static final String LOCAL_ID = "LocalID";

    private static final Logger log = LoggerFactory.getLogger(AllObjs.class);

    static private final KeyLockManager lockManager = KeyLockManagers.newLock();

    public static AllObjs get(String projectId){
        Cache<String, AllObjs> allObjsCache = EhCaches.getCache(EhCaches.ALL_OBJS_UNDER_PROJECT, String.class, AllObjs.class);
        //double-check模式
        if (allObjsCache.get(projectId) == null) {
            lockManager.executeLocked(projectId, ()->{
                if (allObjsCache.get(projectId) == null){
                    AllObjs allObjs = new AllObjs(projectId);
                    allObjs.synFromDb();
                    allObjsCache.put(projectId, allObjs);
                }
            });
        }
        return allObjsCache.get(projectId);
    }

    public static void clearCache(String projectId){
        Cache<String, AllObjs> allObjsCache = EhCaches.getCache(EhCaches.ALL_OBJS_UNDER_PROJECT, String.class, AllObjs.class);
        log.info("Clear allObj cache for project :" + projectId);
        allObjsCache.remove(projectId);
    }

    //前头不带Pj
    private String projectId;

    public AllObjs(String projectId) {
        this.projectId = projectId;
    }

    private Map<String, SearchViewBaseObj> idToObjMap = new HashMap<>();

    public Map<String, SearchViewBaseObj> getIdToObjMap() {
        return idToObjMap;
    }

    public Map<String, List<SearchViewBaseObj>> getCateToObjs() {
        return cateToObjs;
    }

    //两位系统类型或四位设备类型到其实例list的映射
    private Map<String, List<SearchViewBaseObj>> cateToObjs = new HashMap<>();


    //system or equipment id  --> subtype
    private Map<String, String> idToSubtype  = new HashMap<>(128);

    public Map<String, String> getIdToSubtype() {
        return idToSubtype;
    }

    private void handleRoomFuncTypeInfos(Map<String, SearchViewBaseObj> tmpIdToObjMap, List<JSONObject>  roomFuncTypeLst){
        roomFuncTypeLst.forEach(infoJson -> {
            String id = CommonUtil.combineId(projectId, (String)infoJson.get(ObjInfosTable.KEY_OBJ_TYPE), (String)infoJson.get(ObjInfosTable.KEY_OBJ_ID));
            SearchViewBaseObj obj = tmpIdToObjMap.get(id);
            if(obj == null){
                return;
            }
            SVSpObj svSpObj = (SVSpObj)obj;
            this.compareAndSetRoomFuncType(svSpObj, infoJson);
        });
    }

    private void compareAndSetRoomFuncType(SVSpObj svSpObj, JSONObject infoJson){
        if(svSpObj.getRoomFuncType() == null){
            svSpObj.setRoomFuncType(new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get(ObjInfosTable.KEY_TIME).toString()));
            return;
        }
        if(svSpObj.getRoomFuncType().getEffectiveTime().compareTo(infoJson.get(ObjInfosTable.KEY_TIME).toString()) < 0){
            svSpObj.getRoomFuncType().setEffectiveTime(infoJson.get(ObjInfosTable.KEY_TIME).toString());
            svSpObj.getRoomFuncType().setValue(CommonUtil.getValue(infoJson).toString());
        }
    }

    public void synFromDb(){
        String[] infos = {"BuildLocalName", "BuildName", "FloorLocalName", "FloorName",
                "RoomLocalName", "RoomName", "SysLocalName", "SysName", "EquipLocalName", "EquipName", "ProjRoomFuncType", "ShaftLocalName",
                "ShaftName", "BuildLocalID", "FloorLocalID", "RoomLocalID", "SysLocalID", "EquipLocalID", "ShaftLocalID"};

        //此处可以优化，batch_select_merge 可改成batch_select
        JSONObject json = JSONObject.parseObject("{\"QueryType\":\"combine_select\",\"Datatable\":\"obj_infos\"}");
        json.put("Database", OssUtils.getProperty("database.name"));
        JSONArray criterias = new JSONArray();
        Arrays.stream(infos).forEach(info -> {
            JSONObject criteria = new JSONObject();
            criteria.put(ObjInfosTable.KEY_PJ_ID, projectId);
            criteria.put(ObjInfosTable.KEY_INFO_ID, info);
            criterias.add(criteria);
        });
        json.put("Criterias", criterias);
        JSONObject result = null;
        try {
            result = ZillionAgentProvider.GetAgent().Query(json);
        } catch (Exception e) {
            log.error(Arrays.toString(e.getStackTrace()));
        }
        JSONArray arr = (JSONArray) result.get("Content");
        Map<String, SearchViewBaseObj> tmpIdToObjMap = new HashMap<>();
        String nowTimeStr = CommonUtil.getTime();
        Set<String> ids = this.getAllValidObject();

        List<JSONObject>  roomFuncTypeLst = new ArrayList<>();
        for(int i = 0; i < arr.size(); i++){
            JSONObject infoJson = (JSONObject) arr.get(i);
            if(infoJson.get(ObjInfosTable.KEY_TIME).toString().compareTo(nowTimeStr) > 0){
                continue;
            }
            String id = CommonUtil.combineId(projectId, (String)infoJson.get(ObjInfosTable.KEY_OBJ_TYPE), (String)infoJson.get(ObjInfosTable.KEY_OBJ_ID));
            if(!ids.contains(id)){
                continue;
            }
            if(id.toLowerCase().startsWith("vo")){
                continue;
            }
            if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().equalsIgnoreCase("ProjRoomFuncType")){
                roomFuncTypeLst.add(infoJson);
                continue;
            }
            SearchViewBaseObj obj = tmpIdToObjMap.get(id);
            if(obj == null){
                obj = generateObj(infoJson);
                if(obj == null){
                    continue;
                }
                tmpIdToObjMap.put(obj.getId(), obj);
                continue;
            }
            if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_NAME)){
                this.compareAndSetLocalName(obj, infoJson);
            }else if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_ID)){
                this.compareAndSetLocalId(obj, infoJson);
            }else{
                this.compareAndSetSysName(obj, infoJson);
            }
        }
        this.handleRoomFuncTypeInfos(tmpIdToObjMap, roomFuncTypeLst);
        if(tmpIdToObjMap.size() > 0){
            synRelation(tmpIdToObjMap);
            handleOtherInfo(tmpIdToObjMap);
            idToObjMap = tmpIdToObjMap;
        }
    }

    private Set<String> getAllValidObject(){
        JSONObject json = JSONObject.parseObject("{\"QueryType\":\"select\",\"Datatable\":\"objects\"}");
        json.put("Database", OssUtils.getProperty("database.name"));
        JSONObject criteria = new JSONObject();
        criteria.put(ObjectTable.KEY_PJ_ID, this.projectId);
        json.put("Criteria", criteria);
        JSONObject result = null;
        Set<String> ids = new HashSet<>();
        try {
            result = ZillionAgentProvider.GetAgent().Query(json);
        } catch (Exception e) {
            log.error("Exception", e);
            return  ids;
        }

        JSONArray arr = (JSONArray) result.get("Content");
        StringBuilder sb = new StringBuilder();

        for(int i = 0; i < arr.size(); i++){
            JSONObject item = (JSONObject) arr.get(i);
            Object vld = item.get(ObjectTable.COL_VALID);
            if(null == vld) {
                sb.append(item.toString());
                continue;
            }
            if((Boolean) item.get(ObjectTable.COL_VALID)){
                String id = CommonUtil.combineId((String)item.get(ObjectTable.KEY_PJ_ID), (String)item.get(ObjectTable.KEY_OBJ_TYPE), (String)item.get(ObjectTable.KEY_OBJ_ID));
                if(!id.toLowerCase().startsWith("vo")){
                    ids.add(id);
                }
                if(id.startsWith("Sy") || id.startsWith("Eq")){
                    idToSubtype.put(id, (String)item.get(ObjectTable.COL_SUBTYPE));
                }
            }
        }

        log.error("valid=null:" + sb.toString());
        return ids;
    }

    private void compareAndSetLocalName(SearchViewBaseObj obj, JSONObject infoJson){
        if(obj.getLocalName() == null){
            obj.setLocalName(new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()));
            return;
        }
        if(obj.getLocalName().getEffectiveTime().compareTo(infoJson.get(ObjInfosTable.KEY_TIME).toString()) < 0){
            obj.getLocalName().setEffectiveTime(infoJson.get(ObjInfosTable.KEY_TIME).toString());
            obj.getLocalName().setValue(CommonUtil.getValue(infoJson).toString());
        }
    }

    private void compareAndSetSysName(SearchViewBaseObj obj, JSONObject infoJson){
        if(obj.getSysName() == null){
            obj.setSysName(new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()));
            return;
        }
        if(obj.getSysName().getEffectiveTime().compareTo(infoJson.get(ObjInfosTable.KEY_TIME).toString()) < 0){
            obj.getSysName().setEffectiveTime(infoJson.get(ObjInfosTable.KEY_TIME).toString());
            obj.getSysName().setValue(CommonUtil.getValue(infoJson).toString());
        }
    }

    private void compareAndSetLocalId(SearchViewBaseObj obj, JSONObject infoJson){
        if(obj.getLocalId() == null){
            obj.setLocalId(new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()));
            return;
        }
        if(obj.getLocalId().getEffectiveTime().compareTo(infoJson.get(ObjInfosTable.KEY_TIME).toString()) < 0){
            obj.getLocalId().setEffectiveTime(infoJson.get(ObjInfosTable.KEY_TIME).toString());
            obj.getLocalId().setValue(CommonUtil.getValue(infoJson).toString());
        }
    }


    private SearchViewBaseObj generateObj(JSONObject infoJson){
        String id = CommonUtil.combineId((String)infoJson.get(ObjInfosTable.KEY_PJ_ID), (String)infoJson.get(ObjInfosTable.KEY_OBJ_TYPE), (String)infoJson.get(ObjInfosTable.KEY_OBJ_ID));
        if(id.toLowerCase().startsWith("vo")){
            return null;
        }
        if(id.startsWith("Eq")){
            if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_NAME)){
                return new SVEqObj(id, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null);
            }else if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_ID)){
                return new SVEqObj(id, null, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()));
            }else{
                return new SVEqObj(id, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null, null);
            }
        }else if(id.startsWith("Sy")){
            if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_NAME)){
                return new SVSyObj(id, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null);
            }else if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_ID)){
                return new SVSyObj(id, null, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()));
            }else{
                return new SVSyObj(id, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null, null);
            }
        }else if(id.startsWith("Sp")){
            if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_NAME)){
                return new SVSpObj(id, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null);
            }else if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_ID)){
                return new SVSpObj(id, null, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()));
            }else{
                return new SVSpObj(id, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null, null);
            }
        }else if(id.startsWith("Fl")){
            if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_NAME)){
                return new SVFlObj(id, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null);
            }else if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_ID)){
                return new SVFlObj(id, null, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()));
            }else{
                return new SVFlObj(id, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null, null);
            }
        }else if(id.startsWith("Sh")){
            if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_NAME)){
                return new SVShObj(id, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null);
            }else if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_ID)){
                return new SVShObj(id, null, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()));
            }else{
                return new SVShObj(id, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null, null);
            }
        }else if(id.startsWith("Bd")){
            if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_NAME)){
                return new SVBdObj(id, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null);
            }else if(infoJson.get(ObjInfosTable.KEY_INFO_ID).toString().contains(LOCAL_ID)){
                return new SVBdObj(id, null, null, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()));
            }else{
                return new SVBdObj(id, new InformationPoint(CommonUtil.getValue(infoJson).toString(), infoJson.get("time").toString()), null, null);
            }
        }
        return null;
    }

    private List<String> queryGraphIds(){
        List<String> resultList = new ArrayList<>();

        String nowTimeStr = CommonUtil.getTime();
        JSONObject json = JSONObject.parseObject("{\"QueryType\":\"combine_select\",\"Datatable\":\"rel_btw_graph_period\"}");
        json.put("Database", OssUtils.getProperty("database.name"));

        JSONArray criterias = new JSONArray();
        String[] graphTypes = {"EquipinSpace", "SystemEquip", "Subset", "ShaftandBuilding"};
        Arrays.stream(graphTypes).forEach(graphType -> {
            JSONObject criteria = new JSONObject();
            criteria.put(RelBtwGraphPeriodFields.project_id.name(), projectId);
            criteria.put(RelBtwGraphPeriodFields.graph_type.name(), graphType);
            criterias.add(criteria);
        });

        json.put("Criterias", criterias);
        JSONObject result = null;
        try {
            result = ZillionAgentProvider.GetAgent().Query(json);
        } catch (Exception e) {
            log.error(Arrays.toString(e.getStackTrace()));
        }
        JSONArray arr = (JSONArray) result.get("Content");
        for(int i = 0; i < arr.size(); i++){
            JSONObject graphObj =  (JSONObject)arr.get(i);
            if(graphObj.get(RelBtwGraphPeriodFields.begin_time.name()).toString().compareTo(nowTimeStr) <= 0
                    && graphObj.get(RelBtwGraphPeriodFields.end_time.name()).toString().compareTo(nowTimeStr) > 0){
                resultList.add(String.join("","Gt", graphObj.get(RelBtwGraphPeriodFields.graph_type.name()).toString(),
                        graphObj.get(RelBtwGraphPeriodFields.sequence_id.name()).toString()));
            }
        }
        return resultList;
    }

    private void synRelation(Map<String, SearchViewBaseObj> tmpIdToObjMap){
        JSONObject json = JSONObject.parseObject("{\"QueryType\":\"combine_select\",\"Datatable\":\"rel_btw_objs\"}");
        json.put("Database", OssUtils.getProperty("database.name"));
        JSONArray criterias = new JSONArray();
        List<String> graphIds = this.queryGraphIds();
        if(graphIds.isEmpty()){
            return;
        }
        graphIds.forEach(graphId -> {
            JSONObject criteria = new JSONObject();
            criteria.put(RelTable.KEY_PJ_ID, projectId);
            criteria.put(RelTable.KEY_GRAPH_ID, graphId);
//            criteria.put(RelTable.KEY_REL_TYPE, "1");
            criterias.add(criteria);
        });
        json.put("Criterias", criterias);
        JSONObject result = null;
        try {
            result = ZillionAgentProvider.GetAgent().Query(json);
        } catch (Exception e) {
            log.error(Arrays.toString(e.getStackTrace()));
        }
        JSONArray arr = (JSONArray) result.get("Content");
        EqStaticInfo eqStaticInfo = new EqStaticInfo(projectId);
        for(int i = 0; i < arr.size(); i++){
            JSONObject infoJson = (JSONObject) arr.get(i);
            String fromId = CommonUtil.combineId(projectId, (String)infoJson.get(RelTable.KEY_FROM_OBJ_TYPE), (String)infoJson.get(RelTable.KEY_FROM_OBJ_ID));
            String toId = CommonUtil.combineId(projectId, (String)infoJson.get(RelTable.KEY_TO_OBJ_TYPE), (String)infoJson.get(RelTable.KEY_TO_OBJ_ID));
            String graphType = infoJson.get(RelTable.KEY_GRAPH_ID).toString();
            if(graphType.startsWith("GtEquipinSpace")){
                if((!fromId.startsWith("Eq") && !fromId.startsWith("Sy")) || !toId.startsWith("Sp")){
                    log.error("Invalid relation : " + infoJson.toString());
                    continue;
                }
                SearchViewBaseObj fromBaseObj = tmpIdToObjMap.get(fromId);
                SearchViewBaseObj toBaseObj = tmpIdToObjMap.get(toId);
                if(fromBaseObj == null || toBaseObj == null){
                    log.error("Object not found with relation : " + infoJson.toString());
                    continue;
                }
                SVSpObj spObj = (SVSpObj)toBaseObj;
                if(fromId.startsWith("Eq")){
                    ((SVEqObj)fromBaseObj).setSp(spObj);
                }else {
                    ((SVSyObj)fromBaseObj).setSp(spObj);
                }
            }else if(graphType.startsWith("GtSystemEquip")) {
                if(!fromId.startsWith("Sy")  || !toId.startsWith("Eq")){
                    log.error("Invalid relation : " + infoJson.toString());
                    continue;
                }
                SearchViewBaseObj fromBaseObj = tmpIdToObjMap.get(fromId);
                SearchViewBaseObj toBaseObj = tmpIdToObjMap.get(toId);
                if(fromBaseObj == null || toBaseObj == null){
                    log.error("Object not found with relation : " + infoJson.toString());
                    continue;
                }
                ((SVEqObj)toBaseObj).setSy((SVSyObj) fromBaseObj);

            }else if(graphType.startsWith("GtSubset")){
                this.handleSubsetRelation(infoJson, tmpIdToObjMap, eqStaticInfo);
            }else if(graphType.startsWith("GtShaftandBuilding")){
                this.handleShAndBdRel(infoJson, tmpIdToObjMap);
            }
        }

    }

    private  void handleShAndBdRel(JSONObject infoJson, Map<String, SearchViewBaseObj> map){
        String fromId = CommonUtil.combineId(projectId, (String)infoJson.get(RelTable.KEY_FROM_OBJ_TYPE), (String)infoJson.get(RelTable.KEY_FROM_OBJ_ID));
        String toId = CommonUtil.combineId(projectId, (String)infoJson.get(RelTable.KEY_TO_OBJ_TYPE), (String)infoJson.get(RelTable.KEY_TO_OBJ_ID));
        String relType = infoJson.get(RelTable.KEY_REL_TYPE).toString();
        if(map.get(fromId) == null || map.get(toId) == null || !fromId.startsWith("Sh") || !toId.startsWith("Bd")){
            log.error("Object not found with relation : " + infoJson.toString());
            return;
        }
        if(relType.equalsIgnoreCase("1")){
            ((SVShObj)map.get(fromId)).setBd((SVBdObj)map.get(toId));
        }
    }

    private void handleSubsetRelation(JSONObject infoJson, Map<String, SearchViewBaseObj> map, EqStaticInfo eqStaticInfo){
        String fromId = CommonUtil.combineId(projectId, (String)infoJson.get(RelTable.KEY_FROM_OBJ_TYPE), (String)infoJson.get(RelTable.KEY_FROM_OBJ_ID));
        String toId = CommonUtil.combineId(projectId, (String)infoJson.get(RelTable.KEY_TO_OBJ_TYPE), (String)infoJson.get(RelTable.KEY_TO_OBJ_ID));
        String relType = infoJson.get(RelTable.KEY_REL_TYPE).toString();
        if(map.get(fromId) == null || map.get(toId) == null){
            log.error("Object not found with relation : " + infoJson.toString());
            return;
        }
        switch (relType){
            case "1":     // building  --> floor
                SVFlObj flObj = (SVFlObj)map.get(toId);
                flObj.setBd((SVBdObj)map.get(fromId));
                break;
            case "2":     // building  --> space
                SVSpObj spObj = (SVSpObj)map.get(toId);
                spObj.setBd((SVBdObj)map.get(fromId));
                break;
            case "3":     // building  --> system/equipment/component
                if(toId.startsWith("Sy")){
                    SVSyObj syObj = (SVSyObj)map.get(toId);
                    syObj.setBd((SVBdObj)map.get(fromId));
                    syObj.setMajorId(idToSubtype.get(toId).substring(0,2));
                    syObj.setMajorName(eqStaticInfo.getMajorCodeToNameMap().get(idToSubtype.get(toId).substring(0,2)));
                }else if(toId.startsWith("Eq")){
                    SVEqObj eqObj = (SVEqObj)map.get(toId);
                    eqObj.setBd((SVBdObj)map.get(fromId));
                }
                break;

            case "4":     // floor   -->  space
                spObj = (SVSpObj)map.get(toId);
                spObj.setFl((SVFlObj)map.get(fromId));
                break;
        }
    }

    private void handleOtherInfo(Map<String, SearchViewBaseObj> map){
        map.keySet().forEach(key -> {
            if(key.startsWith("Sp")){
                SVSpObj spObj = (SVSpObj)map.get(key);
                if(spObj.getFl() != null){
                    spObj.setBd(spObj.getFl().getBd());
                }

            }

            if(key.startsWith("Sy")){
                SVSyObj syObj = (SVSyObj)map.get(key);

                String category = idToSubtype.get(key).substring(0, 2);
                List<SearchViewBaseObj> objList = cateToObjs.get(category);
                if(objList == null){
                    objList = new ArrayList<>();
                    cateToObjs.put(category, objList);
                }
                objList.add(syObj);
            }
            if(key.startsWith("Eq")){
                SVEqObj eqObj = (SVEqObj)map.get(key);

                String category = idToSubtype.get(key);
                List<SearchViewBaseObj> objList = cateToObjs.get(category);
                if(objList == null){
                    objList = new ArrayList<>();
                    cateToObjs.put(category, objList);
                }
                objList.add(eqObj);
            }
        });
    }
}
