package com.sagacloud.endpoints;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

//import com.sagacloud.json.JSONArray;
//import com.sagacloud.json.JSONObject;
//import com.sagacloud.json.JSONValue;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sagacloud.cache.cachedObject.QueryObjects;
import com.sagacloud.cache.utils.CacheUtil;
import com.sagacloud.dict.CsStaticInfo;
import com.sagacloud.dict.EqStaticInfo;
import com.sagacloud.dict.TlStaticInfo;
import com.sagacloud.endpoints.item.PhysicalObject;
import com.sagacloud.utils.CommonMethods;
import com.sagacloud.utils.CommonUtil;
import com.sagacloud.utils.Const;
import com.sagacloud.utils.DpUtils;
import com.sagacloud.utils.objects.CommonQueryCriteria;
import com.sagacloud.utils.objects.IncludeExclude;
import com.sagacloud.utils.objects.RelationCriteria;
import com.sagacloud.utils.relationUtils.RelationUtil;


/*
 * Author: Jxing
 * Create Time: 2018/8/1
 */
@Path("fast")
public class CacheQuery {

	@Path("/clearCache")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String clearCache(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr) {
		if(projectId == null || !projectId.startsWith("Pj")) {
			return DpUtils.errorJsonMsg("项目Id错误："+projectId);
		}
		
		QueryObjects.clearCacheByProject(projectId);
		
		JSONObject jsonObj = new JSONObject();
        jsonObj.put("Result", "success");
        jsonObj.put("ResultMsg", "");
        return jsonObj.toString();
	}
	
	@Path("/object/queryAllEq")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String queryAllEq(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr) {
		JSONObject paramJson = JSONObject.parseObject(jsonStr);
		Set<String> returnInfoSet = null;
		if(paramJson.containsKey("returnInfos")) {
			JSONArray returnInfos = paramJson.getJSONArray("returnInfos");
			if(returnInfos != null && !returnInfos.isEmpty()) {
				returnInfoSet = new HashSet<>();
				for(Object obj : returnInfos.toArray()) {
					returnInfoSet.add(obj.toString());
				}
			}
		}
		try {
			return CommonUtil.queryAllEq(projectId, returnInfoSet).toJSONString();
		} catch (Exception e) {
			e.printStackTrace();
			return DpUtils.errorJsonMsg(e.getMessage());
		}
	}
	
    @Path("/object/in_query")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String inQuery(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr) {
        try {
            ArrayList<String> types = new ArrayList<>();
            List<RelationCriteria> include = new ArrayList<>();
            List<RelationCriteria> exclude = new ArrayList<>();
            Set<String> includeIdSet = null;
            Set<String> excludeIdSet = null;
            JSONObject json = JSONObject.parseObject(jsonStr);
            CommonQueryCriteria cqc = CommonUtil.generateCommonQueryCriteria(json);

            if(!json.containsKey("criteria"))
                throw new Exception("缺少criteria节点.");
            JSONObject criteria = (JSONObject) json.get("criteria");
            String id = PhysicalObject.checkIdNode(projectId, criteria);
            cqc.setDirectOnlyId(id);
            if(criteria.containsKey("type") && criteria.get("type") instanceof JSONArray)
            {
                JSONArray ts = (JSONArray) criteria.get("type");
                for(int i = 0; i < ts.size(); ++i)
                    types.add(ts.get(i).toString());
                checkTypesAllowProperty(projectId, types, id);
            }else
                throw new Exception("type节点错误, 请参考文档");
            boolean set = true, accurate = true;
            if(criteria.get("set") != null && criteria.get("set").equals(false))
                set = false;
            if(criteria.get("accurate") != null && criteria.get("accurate").equals(false))
                accurate = false;
            if(criteria.getJSONArray("include") != null && criteria.getJSONArray("include").size() > 0) {
                include = JSONArray.parseArray(criteria.getJSONArray("include").toJSONString(), RelationCriteria.class);
            }
            if(criteria.getJSONArray("exclude") != null && criteria.getJSONArray("exclude").size() > 0) {
                exclude = JSONArray.parseArray(criteria.getJSONArray("exclude").toJSONString(), RelationCriteria.class);
            }
            criteria.remove("id");
            criteria.remove("type");
            criteria.remove("set");
            criteria.remove("accurate");
            criteria.remove("include");
            criteria.remove("exclude");
//            if(criteria.size() == 0)
//                throw new Exception("criteria内容错误");
            Map<String, Set<Object>> infoValueMap = new HashMap<>();
            for(String infoKey : criteria.keySet()){
                JSONArray valueArr = criteria.getJSONArray(infoKey);
                if(valueArr == null || valueArr.size() == 0)
                    throw new Exception("信息点" + infoKey + "值错误");
                if(!infoValueMap.containsKey(infoKey))
                    infoValueMap.put(infoKey, new HashSet<>(valueArr));
            }
            RelationUtil.getGraphId(projectId, include, exclude);
            // includeExclude 里面保存的是要被包含的id set, 要被排除的id set
            IncludeExclude includeExclude = RelationUtil.getIncludeExcludeId(CommonMethods.getProject(projectId, false), include, exclude);
            JSONArray tmp = CacheUtil.getInfoByValueArray(projectId.substring(2), id, types, infoValueMap, includeExclude, set, accurate, cqc);

            if(cqc.getNodata())
                return DpUtils.returnJSONArray(new JSONArray(), "", cqc.getCount());
            return DpUtils.returnJSONArray(tmp, cqc.getSkip_totalCount());
        } catch (Exception ex) {
            ex.printStackTrace();
            return DpUtils.errorJsonMsg(ex.getMessage());
        }
    }

    private void checkTypesAllowProperty(String pjId, ArrayList<String> types, String id) throws Exception {
        EqStaticInfo eqStaticInfo = new EqStaticInfo(pjId);
        for(int i = 0 ; i < types.size(); ++i)
        {
            String type = types.get(i);
            if(id.startsWith(Const.OBJ_TYPE_BUILDING) && (type.equals(Const.OBJ_TYPE_PROJECT)|| type.startsWith(Const.OBJ_TYPE_VO))) // building 不能查项目, 和VO
            {
                throw new Exception("不支持的类型:" + type);
            }
            if(id.startsWith(Const.OBJ_TYPE_FLOOR) && !(type.equals(Const.OBJ_TYPE_FLOOR) || type.equals(Const.OBJ_TYPE_SPACE)
                    || type.equals(Const.OBJ_TYPE_ISPACE)|| type.equals(Const.OBJ_TYPE_PROPERTY) ||eqStaticInfo.getFamilySet().contains(type)
                    || PhysicalObject.bussinessSpaceTypeMap.containsKey(type)))// 楼层只能查楼层或者空间, 资产.
            {
                throw new Exception("不支持的类型:" + type);
            }
            if(PhysicalObject.allTypes.contains(type) || eqStaticInfo.getSysSet().contains(type) || eqStaticInfo.getEqSet().contains(type) || eqStaticInfo.getFamilySet().contains(type)
                    || PhysicalObject.bussinessSpaceTypeMap.containsKey(type) || CsStaticInfo.getCode2name().keySet().contains(type) || TlStaticInfo.getCode2name().keySet().contains(type))
            {
                continue;
            }
            throw new Exception("不支持的类型:" + type);
        }
    }
}
