package com.sagacloud.endpoints;

import com.alibaba.fastjson.*;
import com.sagacloud.dict.InfosUtil;
import com.sagacloud.utils.*;
import com.sagacloud.utils.jsonHelper.SubsetEntity;
import com.sagacloud.utils.jsonHelper.infoPoint.InfoPoint;
import com.sagacloud.utils.objectLog.ActivityLogObject;
import com.sagacloud.utils.objectLog.ActivityLogRunnable;
import com.sagacloud.utils.objectLog.ActivityLogUtil;
import com.sagacloud.utils.objects.AffectedBusinessSpace;
import com.sagacloud.utils.objects.CommonQueryCriteria;
import com.sagacloud.utils.objects.ObjectIdName;
import com.sagacloud.utils.objects.ObjectType;
import com.sagacloud.utils.qrCode.QRCodeObj;
import com.sagacloud.utils.qrCode.QRCodeRunnable;
import com.sagacloud.utils.relationUtils.SubsetUtil;

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 java.util.*;

/**
 * Created by Xiaoyu on 2018/5/17
 */
@Path("ispace")
public class ISpace {
	@Path("/batch/create_update")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String createUpdate(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr){
		final String repeat_id = "repeat_id";
    	
        JSONObject postParam = JSONObject.parseObject(jsonStr);
        JSONObject postBody = JSONObject.parseObject(jsonStr);
        // 先批量插入
        String insertBatchResult = batchCreate(projectId, postParam);
        
        JSONObject insetResultBody = JSONObject.parseObject(insertBatchResult);
        JSONArray errorAray = insetResultBody.getJSONArray("Error");
        if(null != errorAray) {
        	insetResultBody.put("error_insert", errorAray);
        	insetResultBody.remove("Error");
        }
        
        // 含有已存在的对象，进行更新操作
        if(insertBatchResult.contains(repeat_id)) {
        	// 已存在对象的id集合
        	Set<String> repeatIdSet = new HashSet<>();
        	JSONArray errorNewAray = new JSONArray();
        	if(null != errorAray) {
        		for(int i=0; i<errorAray.size(); i++) {
        			if(null != errorAray.getJSONObject(i) && null != errorAray.getJSONObject(i).getString(repeat_id)) {
        				repeatIdSet.add(errorAray.getJSONObject(i).getString(repeat_id));
        			}else {
        				errorNewAray.add(errorAray.getJSONObject(i));
        			}
        		}
         	}
        	
        	if(!errorNewAray.isEmpty()) {
        		insetResultBody.put("error_insert", errorNewAray);
        	}else {
        		insetResultBody.remove("error_insert");
        		insetResultBody.put("Result", "success");
        	}
        	
        	
        	if(!repeatIdSet.isEmpty()) {
        		insertBatchResult = ObjectUtil.insertParamToExcuteUpdate(projectId, postBody, insetResultBody, repeatIdSet);
        	}
        }
        
        return insertBatchResult;
    }
	
    @Path("/batch/create")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String batchCreate(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr){
        JSONObject postBody = JSONObject.parseObject(jsonStr);
        return batchCreate(projectId, postBody);
    }

    public String batchCreate(@QueryParam(Const.PROJECT_ID) String projectId, JSONObject postBody){
        try{
            String imageUrl = postBody.getString("innerImageUrl");
            Boolean genPersagyQr = postBody.getBoolean("genPersagyQr");
            if(genPersagyQr == null){
                genPersagyQr = false;
            }
            JSONArray criterias = postBody.getJSONArray("criterias");
            if(criterias == null || criterias.size() == 0){
                return DpUtils.returnJSONArray(new JSONArray(), "");
            }
            JSONArray errors = new JSONArray();
            String pjId = projectId.substring(2);
//            一. 准备数据
//            1. 为每个对象生成id, 或者检验指定的id符不符合规则, 检验是否有重复指定的id.
//            2. 统计  设备/系统/部件/业务空间/元空间 类型, 获取每个类型下的信息点列表. (剔除错误类型)
            JSONCheckUtil.checkSiGenerateId(pjId, criterias, errors);
            HashMap<String, HashMap<String, InfoPoint>> infoCodeMap = InfoCodeUtil.getWholeInfosWithCustomMap(pjId, ObjectType.ispace.name());
//            3. 通过2获取到的信息点列表, 验证信息点的key是否正确(剔除错误)
//            4. 验证信息点节点的格式是否正确.
            JSONCheckUtil.verifySpaceInfos(pjId, criterias, infoCodeMap, errors);
//            5. 统计  building_id, floor_id(仅设备允许), (跳过关系id错误的关系).
            Map<String, String> buildingMap = new HashMap<>();  // id --> building_id
            Map<String, String> floorMap = new HashMap<>();     // id --> floor_id
            JSONCheckUtil.countEquipRelation(pjId, buildingMap, floorMap, null, criterias, errors); // 填充上面两个Map
//            6. 查看是否有二维码信息点EquipQRCode, 有的话不再插入二维码, 没有的话, 添加二维码信息点, 同时记录id(用于接口返回后添加二维码图片).
            Map<String, String> idFileKeyMap = new HashMap<>();
            JSONCheckUtil.addQRCodeInfo(projectId, criterias, "RoomQRCode", idFileKeyMap);
//            二. 插入数据
//            1. 插入对象表 (将失败的剔除)
            if(criterias.size() == 0)
                return PropertyUtil.returnOnCreation(criterias, errors, "");
            String time = CommonUtil.getTime();
            DpUtils.submitToObjectTable(pjId, criterias, time, errors);
            // 补充信息点数据
            ArrayList<ActivityLogObject> logList = new ArrayList<>();
            for(int i = 0; i < criterias.size(); ++i) {
                JSONObject single = criterias.getJSONObject(i);
                String id = single.getString("id");
                ObjectType ot = ObjectUtil.getObjectTypeById(id);
                InfosUtil.addIdName(pjId, ot, null, single.getJSONObject("infos"), id, new ObjectIdName());
                // 添加要发送到activeMQ的消息
                ActivityLogUtil.addMessageToQueue(pjId, time, logList, id, ot);
            }
            JSONArray success = new JSONArray();
            PropertyUtil.putIDToInfos(criterias, success);

//            2. 插入关系
            try {
                List<SubsetEntity> relationList = new ArrayList<>();
                Set<String> relationIdSet = new HashSet<>();
                relationIdSet.addAll(buildingMap.values());
                relationIdSet.addAll(floorMap.values());
                ObjectUtil.filterValid(pjId, relationIdSet, true, null);
                for(int i = 0; i < criterias.size(); ++i){
                    JSONObject single = criterias.getJSONObject(i);
                    String id = single.getString("id");
                    if(floorMap.get(id) != null && relationIdSet.contains(floorMap.get(id))){
                        SubsetEntity se = new SubsetEntity(floorMap.get(id), id);
                        relationList.add(se);
                    }else if(buildingMap.get(id) != null && relationIdSet.contains(buildingMap.get(id))){
                        SubsetEntity se = new SubsetEntity(buildingMap.get(id), id);
                        relationList.add(se);
                    }
                }
                SubsetUtil.modify(pjId, relationList);
            }catch (Exception ignore){}
//            3. 插入信息点
            ObjectUtil.batchUpdate(pjId, criterias, false, true, false, new CommonQueryCriteria());
//            三. 接口返回后
//            1. 发送activeMQ消息, 记录日志
            ActivityLogRunnable activityLog = new ActivityLogRunnable(logList);
            ActivityLogUtil.pool.submit(activityLog);
//            2. 生成二维码文件, 上传到文件服务器
            QRCodeRunnable qrCodeRunnable = new QRCodeRunnable(idFileKeyMap, imageUrl, projectId, genPersagyQr);
            ActivityLogUtil.pool.submit(qrCodeRunnable);
            return PropertyUtil.returnOnCreation(success, errors, "");
        }catch (Exception ex){
            ex.printStackTrace();
            return DpUtils.errorJsonMsg(ex.getMessage() == null? "添加失败!": ex.getMessage());
        }
    }
    @Path("/create")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String create(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr){
        JSONObject obj = JSONObject.parseObject(jsonStr);
        JSONObject postBody = new JSONObject();
        JSONArray criterias = new JSONArray();
        criterias.add(obj);
        postBody.put("criterias", criterias);
        String result = batchCreate(projectId, postBody);
        JSONObject criteria = JSONObject.parseObject(result);
        return DpUtils.batchToSingle(criteria);
    }
//    旧元空间单条创建接口, 未支持二维码
//    @Path("/create")
//    @POST
//    @Produces(MediaType.APPLICATION_JSON)
//    public String create(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr){
//        try {
//            JSONObject insertJson = JSONObject.parseObject(jsonStr);
//            if(!insertJson.containsKey(Const.JSON_FIELD_JSON_DATA_INFOS)){
//                return DpUtils.errorJsonMsg("缺少必要字段");
//            }
//            String floor_id = null;
//            String building_id = null;
//            if(insertJson.get("floor_id") != null){
//                floor_id = insertJson.get("floor_id").toString();
//                // check if floor exist
//                JSONObject checkCriteria = new JSONObject();
//                checkCriteria.put(ObjectTable.KEY_PJ_ID, projectId.substring(2));
//                checkCriteria.put(ObjectTable.KEY_OBJ_TYPE, Const.OBJ_TYPE_FLOOR);
//                checkCriteria.put(ObjectTable.KEY_OBJ_ID, floor_id.substring(12));
//                checkCriteria.put(Const.TABLE_KEY_NAME_VALID, true);
//                if(CommonUtil.getCount(HBaseTable.objects, checkCriteria) <= 0)
//                    throw new Exception("楼层不存在.");
//                // check end.
//            }else if(insertJson.get("building_id") != null){
//                building_id = insertJson.get("building_id").toString();
//                // check if building exist
//                JSONObject checkCriteria = new JSONObject();
//                checkCriteria.put(ObjectTable.KEY_PJ_ID, projectId.substring(2));
//                checkCriteria.put(ObjectTable.KEY_OBJ_TYPE, Const.OBJ_TYPE_BUILDING);
//                checkCriteria.put(ObjectTable.KEY_OBJ_ID, building_id.substring(12));
//                checkCriteria.put(Const.TABLE_KEY_NAME_VALID, true);
//                if(CommonUtil.getCount(HBaseTable.objects, checkCriteria) <= 0)
//                    throw new Exception("建筑体不存在.");
//                // check end.
//            }
//            String assignedObjId = null;
//            if(insertJson.get("id") != null )
//            {
//                if(insertJson.get("id").toString().startsWith(Const.OBJ_TYPE_ISPACE)) {
//                    String spId = insertJson.get("id").toString();
//                    assignedObjId = spId.substring(12);
//                    if (!DpUtils.verifyAssignedObjID(assignedObjId)) {
//                        return DpUtils.errorJsonMsg("指定的id错误.");
//                    }
//                }else
//                    return DpUtils.errorJsonMsg("指定的id错误.");
//            }
//
//            ObjectIdName name = new ObjectIdName();
//            String id = ObjectUtil.addObj(projectId.substring(2), Const.OBJ_TYPE_ISPACE,"",
//                    (JSONObject) insertJson.get(Const.JSON_FIELD_JSON_DATA_INFOS), ObjectType.ispace, name, assignedObjId, true);
//            if(floor_id != null){
//                //insert floor-space relation
//                SubsetUtil.addRel(projectId, floor_id, id);
//            }else if(building_id != null){
//                //insert building-space relation
//                SubsetUtil.addRel(projectId, building_id, id);
//            }
//            return DpUtils.successJsonMsgWithId("", id, name.getNameKey(), name.getNameValue());
//        }catch (Exception ex)
//        {
//            ex.printStackTrace();
//            return DpUtils.errorJsonMsg(ex.getMessage() == null? "添加失败!": ex.getMessage());
//        }
//    }

    @Path("/delete")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String delete(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr){
        try {
            JSONObject criteria = JSONObject.parseObject(jsonStr);
            criteria = (JSONObject) criteria.get("criteria");
            CommonUtil.deleteObject(criteria.get("id").toString(), criteria.get("id").toString().substring(2, 12),
                    criteria.get("id").toString().substring(0, 2), criteria.get("id").toString().substring(12), ObjectType.ispace,true);
            AffectedBusinessSpace abs = new AffectedBusinessSpace(projectId.substring(2), criteria.get("id").toString(), (String) criteria.get("graphId"));
            ActivityLogUtil.pool.submit(abs);
            return DpUtils.successJsonMsg("");
        }catch (Exception ex)
        {
            ex.printStackTrace();
            return DpUtils.errorJsonMsg(ex.getMessage());
        }
    }
}
