package com.sagacloud.endpoints;


import com.alibaba.fastjson.*;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.sagacloud.endpointService.VirtualObjectService;
import com.sagacloud.utils.*;
import com.sagacloud.utils.objects.ObjectIdName;
import com.sagacloud.utils.objects.ObjectType;
import com.sagacloud.utils.tables.HBaseTable;
import com.sagacloud.utils.tables.ObjInfosTable;
import com.sagacloud.utils.tables.ObjectTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.ArrayList;

@Path("vo")
public class VirtualObject {
    private static final Logger log = LoggerFactory.getLogger(VirtualObject.class);
    // VOCu : 计算单元,  VOEi: 能源分项, VOTn: 租户, VOBr: 支路, VOMt: 仪表
    public static final ArrayList<String> allowedVO = CommonUtil.createArrayList(
            "VOCu", "VOBd", "VOEi", "VOTn", "VOZn", "VOGp", "VOCt", "VOBc", "VOSe", "VOSc", "VOSh", "VOSw", "VOSg",
            "VOSf", "VOSv", "VOBr", "VOMt");

    @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("type") || !insertJson.containsKey(Const.JSON_FIELD_JSON_DATA_INFOS)) {
                return DpUtils.errorJsonMsg("缺少必要字段");
            }
            if (!allowedVO.contains(insertJson.get("type").toString()))
                throw new Exception("不支持的虚拟类型");
            ObjectIdName name = new ObjectIdName();
            String userId = insertJson.getString("id");
            if (userId != null && userId.length() != 0) {
                if (!DpUtils.checkId(projectId, userId))
                    throw new Exception("指定id错误");
            }
            String id = ObjectUtil.addVirtualObj(projectId.substring(2), insertJson.get("type").toString(), userId,
                    (JSONObject) insertJson.get(Const.JSON_FIELD_JSON_DATA_INFOS), getObjectType(insertJson.get("type").toString()), name, false);
            return DpUtils.successJsonMsgWithId("", id, null, null);
        } catch (Exception ex) {
            ex.printStackTrace();
            return DpUtils.errorJsonMsg(ex.getMessage() == null ? "添加失败!" : ex.getMessage());
        }
    }

    @Path("/batch/create")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String batchCreate(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr) {
        JSONObject json = JSONObject.parseObject(jsonStr);
        return batchCreate(projectId, json);
    }

    public String batchCreate(String projectId, JSONObject postBody) {
        try {
            JSONArray criterias = postBody.getJSONArray("criterias");
            if (criterias == null || criterias.size() == 0) {
                return DpUtils.returnJSONArray(new JSONArray(), "");
            }
            JSONArray errors = new JSONArray();
            JSONArray success = new JSONArray();
            ObjectUtil.batchAddVirtualObj(projectId.substring(2), criterias, success, errors);
            return PropertyUtil.returnOnCreation(success, errors, "");
        } catch (Exception ex) {
            ex.printStackTrace();
            return DpUtils.errorJsonMsg(ex.getMessage() == null ? "添加失败!" : ex.getMessage());
        }
    }


    @Path("/batch/delete")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String batchDelete(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr) {
        JSONObject json = JSONObject.parseObject(jsonStr);
        return batchDelete(projectId, json);
    }

    public String batchDelete(String projectId, JSONObject postBody) {
        try {
            JSONArray criterias = postBody.getJSONArray("criterias");
            if (criterias == null || criterias.size() == 0) {
                return DpUtils.returnJSONArray(new JSONArray(), "");
            }
            JSONArray errors = new JSONArray();
            VirtualObjectService.batchDeleteVirtualObj(projectId.substring(2), criterias, errors);
            if (errors.size() > 0)
                return PropertyUtil.returnJSON(criterias.size() != 0, null, errors, "");
            return DpUtils.successJsonMsg("删除成功");
        } catch (Exception ex) {
            ex.printStackTrace();
            return DpUtils.errorJsonMsg(ex.getMessage() == null ? "删除失败!" : ex.getMessage());
        }
    }


    public static ObjectType getObjectType(String type) throws Exception {
        switch (type) {
            case "VOBd":
                return ObjectType.VOBd;
            default:
                return ObjectType.VO;
        }
    }

    @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");
            if (!criteria.containsKey("id") || criteria.get("id") == null || !allowedVO.contains(criteria.get("id").toString().substring(0, 4)))
                throw new Exception("id错误!");

            // check if all facility, system and floor belong to this building all been deleted
//
//            if(isDeletable(criteria.get("id").toString()))
//                throw new Exception("请先删除建筑下面的设备、楼层和空间!");

            // delete all relation with this building.
//            JSONArray relationArray = new JSONArray();
//            JSONObject from_relation = new JSONObject();
//            from_relation.put("from_id", criteria.get("id").toString());
//            JSONObject to_relation = new JSONObject();
//            to_relation.put("to_id", criteria.get("id").toString());
//            relationArray.add(from_relation);
//            relationArray.add(to_relation);
//            JSONObject obj = new JSONObject();
//            obj.put("criterias", relationArray);
//            RelationUtil.deleteRelation(criteria.get("id").toString().substring(2), obj);
//            log.info("已删除虚拟对象" + criteria.get("id").toString() + "的所有关系.");
            //
            // set building to false
            JSONObject updateCriteria = new JSONObject();
            JSONObject set = new JSONObject();
            updateCriteria.put(ObjInfosTable.KEY_PJ_ID, projectId.substring(2));
            updateCriteria.put(ObjInfosTable.KEY_OBJ_TYPE, criteria.get("id").toString().substring(0, 4));
            updateCriteria.put(ObjInfosTable.KEY_OBJ_ID, criteria.get("id").toString().substring(14));
            set.put(Const.TABLE_KEY_NAME_VALID, false);
            set.put(ObjectTable.KEY_DEL_TIME, CommonUtil.getTime());
            JSONObject result = CommonUtil.update(false, HBaseTable.objects, updateCriteria, set);
            if (result.get("Count").equals(0))  // 如果更新失败
                return DpUtils.errorJsonMsg("删除失败或者没有数据.");
            //CommonUtil.deleteInfoPointToHistory(projectId.substring(2), criteria.get("id").toString().substring(0, 4), criteria.get("id").toString().substring(14));
            return DpUtils.successJsonMsg("");
        } catch (Exception ex) {
            ex.printStackTrace();
            return DpUtils.errorJsonMsg(ex.getMessage());
        }
    }

    private boolean isDeletable(String buildingId) throws Exception {
        JSONArray eq_fl_sy_arr = new JSONArray();
        JSONObject eq_criteria = new JSONObject();
        JSONObject fl_criteria = new JSONObject();
        JSONObject sy_criteria = new JSONObject();
        JSONObject sp_criteria = new JSONObject();
        JSONObject eq_type_range = new JSONObject();
        JSONObject eq_id_range = new JSONObject();
        JSONObject sy_type_range = new JSONObject();
        JSONObject sy_id_range = new JSONObject();
        JSONObject fl_id_range = new JSONObject();
        JSONObject sp_id_range = new JSONObject();
        eq_type_range.put("$gte", Const.OBJ_TYPE_EQUIPMENT);
        eq_type_range.put("$lte", Const.OBJ_TYPE_EQUIPMENT + "zzzzzz");
        eq_id_range.put("$gte", buildingId.substring(12));
        eq_id_range.put("$lte", buildingId.substring(12) + "zzzzzz");
        sy_type_range.put("$gte", Const.OBJ_TYPE_SYSTEM);
        sy_type_range.put("$lte", Const.OBJ_TYPE_SYSTEM + "zzzzzz");
        sy_id_range.put("$gte", buildingId.substring(12));
        sy_id_range.put("$lte", buildingId.substring(12) + "zzzzzz");
        fl_id_range.put("$gte", buildingId.substring(12));
        fl_id_range.put("$lte", buildingId.substring(12) + "zzzzzz");
        sp_id_range.put("$gte", buildingId.substring(12) + "000");
        sp_id_range.put("$lte", buildingId.substring(12) + "000zzzz");
        eq_criteria.put(ObjectTable.KEY_PJ_ID, buildingId.substring(2, 12));
        eq_criteria.put(ObjectTable.KEY_OBJ_TYPE, eq_type_range);
        eq_criteria.put(ObjectTable.KEY_OBJ_ID, eq_id_range);
        eq_criteria.put(Const.TABLE_KEY_NAME_VALID, true);
        sy_criteria.put(ObjectTable.KEY_PJ_ID, buildingId.substring(2, 12));
        sy_criteria.put(ObjectTable.KEY_OBJ_TYPE, sy_type_range);
        sy_criteria.put(ObjectTable.KEY_OBJ_ID, sy_id_range);
        sy_criteria.put(Const.TABLE_KEY_NAME_VALID, true);
        fl_criteria.put(ObjectTable.KEY_PJ_ID, buildingId.substring(2, 12));
        fl_criteria.put(ObjectTable.KEY_OBJ_TYPE, Const.OBJ_TYPE_FLOOR);
        fl_criteria.put(ObjectTable.KEY_OBJ_ID, fl_id_range);
        fl_criteria.put(Const.TABLE_KEY_NAME_VALID, true);
        sp_criteria.put(ObjectTable.KEY_PJ_ID, buildingId.substring(2, 12));
        sp_criteria.put(ObjectTable.KEY_OBJ_TYPE, Const.OBJ_TYPE_SPACE);
        sp_criteria.put(ObjectTable.KEY_OBJ_ID, sp_id_range);
        sp_criteria.put(Const.TABLE_KEY_NAME_VALID, true);
        eq_fl_sy_arr.add(eq_criteria);
        eq_fl_sy_arr.add(sy_criteria);
        eq_fl_sy_arr.add(fl_criteria);
        eq_fl_sy_arr.add(sp_criteria);
        return CommonUtil.getCount(HBaseTable.objects, eq_fl_sy_arr);
    }

}