package com.sagacloud.endpoints;

//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.broadcast.MessageHandler;
import com.sagacloud.dict.EqStaticInfo;
import com.sagacloud.endpoints.customDict.CtmDict;
import com.sagacloud.utils.CommonUtil;
import com.sagacloud.utils.Const;
import com.sagacloud.utils.DpUtils;
import com.sagacloud.utils.InfoCodeUtil;
import com.sagacloud.utils.tables.HBaseTable;
import com.sagacloud.utils.tables.InfocodeSchemeTable;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

@Path("custom_infocode")
public class CustomInfoCode {

    @Context
    private ResourceContext resourceContext;

    @Path("/scheme/create")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String createScheme(String jsonStr) {
        JSONObject json = JSONObject.parseObject(jsonStr);
        if (json.get(InfocodeSchemeTable.SCHEME_NAME) == null) {
            return DpUtils.errorJsonMsg("missing key : " + InfocodeSchemeTable.SCHEME_NAME);
        }
        UUID uuid = UUID.randomUUID();
        String schemeId = uuid.toString().replace("-", "");
        json.put(InfocodeSchemeTable.SCHEME_ID, schemeId);
        try {
            JSONObject re = CommonUtil.insert(false, HBaseTable.infocode_scheme, json);
            if (re.get("Result").toString().equals("success")) {
                re = JSONObject.parseObject(DpUtils.successJsonMsg(""));
                re.put(InfocodeSchemeTable.SCHEME_ID, schemeId);
                return re.toString();
            }
            return DpUtils.errorJsonMsg("已存在");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    @Path("/scheme/query")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String queryScheme(String jsonStr) {
        HashMap<String,Set<String>> followerMap = new HashMap<>();
        JSONObject json = JSONObject.parseObject(jsonStr);
        try {

            JSONObject re = CommonUtil.query(false,HBaseTable.infocode_scheme_follower,new JSONObject());
            JSONArray followerContent = (JSONArray) re.get("Content");
            for(int i = 0; i < followerContent.size(); ++i){
                JSONObject obj = (JSONObject) followerContent.get(i);
                String pjId = Const.OBJ_TYPE_PROJECT+obj.get(InfocodeSchemeTable.PJ_ID).toString();
                String schemeId = obj.get(InfocodeSchemeTable.SCHEME_ID).toString();
                if(!followerMap.containsKey(schemeId)){
                    followerMap.put(schemeId,new HashSet<>());
                }
                Set<String> pjSet = followerMap.get(schemeId);
                pjSet.add(pjId);
            }

            re = CommonUtil.query(false, HBaseTable.infocode_scheme, (JSONObject) json.get("criteria"));
            if (!re.get("Result").toString().equals("success")) {
                return DpUtils.errorJsonMsg("查询出错 : " + re.toString());
            }
            JSONArray content = (JSONArray) re.get("Content");

            for(int i = 0; i < content.size(); ++i){
                JSONObject node = (JSONObject) content.get(i);
                String schemeId = node.get(InfocodeSchemeTable.SCHEME_ID).toString();
                if(followerMap.containsKey(schemeId)){
                    JSONArray followers = new JSONArray();
                    for(String pjId : followerMap.get(schemeId)){
                        followers.add(pjId);
                    }
                    node.put("followers",followers);
                }

            }
            return DpUtils.returnJSONArray((JSONArray) re.get("Content"), "");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    @Path("/scheme/update")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String updateScheme(String jsonStr) {
        JSONObject json = JSONObject.parseObject(jsonStr);
        if (((JSONObject) json.get("criteria")).get(InfocodeSchemeTable.SCHEME_ID) == null) {
            return DpUtils.errorJsonMsg("criteria must contain key : " + InfocodeSchemeTable.SCHEME_ID);
        }
        try {
            JSONObject re = CommonUtil.update(false, HBaseTable.infocode_scheme, json.get("criteria"), json.get("set"));
            if (re.getLongValue("Count") > 0) {
                return DpUtils.successJsonMsg("");
            }
            return DpUtils.errorJsonMsg("所要更新的scheme_id不存在");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    @Path("/scheme/delete")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String deleteScheme(String jsonStr) {
        JSONObject json = JSONObject.parseObject(jsonStr);
        JSONObject criteria = (JSONObject) json.get("criteria");
        if (criteria.get(InfocodeSchemeTable.SCHEME_ID) == null) {
            return DpUtils.errorJsonMsg("criteria must contain key : " + InfocodeSchemeTable.SCHEME_ID);
        }
        try {
            JSONObject re = null;
            re = CommonUtil.getCount(false, HBaseTable.infocode_scheme_follower, criteria);
            if (re.getLongValue("Count") != 0) {
                return DpUtils.errorJsonMsg("该方案正在被使用");
            }
            re = CommonUtil.delete(false, HBaseTable.infocode_scheme, criteria);
            re = CommonUtil.delete(false, HBaseTable.infocode_scheme_detail, criteria);
            return DpUtils.successJsonMsg("");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    @Path("/follower/create")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String createFollower(@QueryParam(Const.PROJECT_ID) String projectId, String jsonStr) {
        projectId = projectId.substring(2);
        JSONObject json = JSONObject.parseObject(jsonStr);//目前只有scheme_id
        try {
            if (json.get(InfocodeSchemeTable.SCHEME_ID) == null) {
                return DpUtils.errorJsonMsg("missing key : " + InfocodeSchemeTable.SCHEME_ID);
            }
            //1.检查是否有该信息点方案
            JSONObject re = CommonUtil.getCount(false, HBaseTable.infocode_scheme, json);
            if (re.getLongValue("Count") == 0) {
                return DpUtils.errorJsonMsg("请先创建信息点方案");
            }
            //1.end
            //2.检查是否已使用其他方案
            JSONObject queryJson = new JSONObject();
            queryJson.put(InfocodeSchemeTable.PJ_ID, projectId);
            re = CommonUtil.query(false,HBaseTable.infocode_scheme_follower,queryJson);
            if(re.getLongValue("Count") != 0 ){
                String schemeId =(String) ((JSONObject)((JSONArray)re.get("Content")).get(0)).get(InfocodeSchemeTable.SCHEME_ID);
                return DpUtils.errorJsonMsg("正在使用方案 : " + schemeId);
            }
            //2.end
            json.put(InfocodeSchemeTable.PJ_ID, projectId);
            re = CommonUtil.insert(false, HBaseTable.infocode_scheme_follower, json);
            if (!re.get("Result").toString().equals("success")) {
                String existedScheme = ((JSONObject) ((JSONArray) re.get("Content")).get(0)).get(InfocodeSchemeTable.SCHEME_ID).toString();
                return DpUtils.errorJsonMsg("只能使用一个方案，已使用方案 : " + existedScheme);
            }
            return DpUtils.successJsonMsg("");

        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    @Path("/follower/query")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String queryFollowerPost(@QueryParam(Const.PROJECT_ID) String projectId){
        return queryFollower(projectId);
    }

    @Path("/follower/query")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public static String queryFollower(@QueryParam(Const.PROJECT_ID) String projectId) {
        projectId = projectId.substring(2);
        JSONObject criteria = new JSONObject();
        criteria.put(InfocodeSchemeTable.PJ_ID, projectId);
        try {
            JSONObject re = null;
            re = CommonUtil.query(false, HBaseTable.infocode_scheme_follower, criteria);
            if (!re.get("Result").toString().equals("success")) {
                return DpUtils.errorJsonMsg("查询出错 : " + HBaseTable.infocode_scheme_follower.name());
            }
            JSONArray content = (JSONArray) re.get("Content");
            if (content.size() == 0) {
                return DpUtils.returnJSONArray(content, "");
            }
            String schemeId = ((JSONObject) content.get(0)).get(InfocodeSchemeTable.SCHEME_ID).toString();
            criteria.clear();
            criteria.put(InfocodeSchemeTable.SCHEME_ID, schemeId);
            re = CommonUtil.batch_get(false, HBaseTable.infocode_scheme, criteria);
            if (!re.get("Result").toString().equals("success")) {
                return DpUtils.errorJsonMsg("查询出错 : " + HBaseTable.infocode_scheme.name());
            }
            content = (JSONArray) re.get("Content");
            return DpUtils.returnJSONArray(content, "");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    @Path("/follower/delete")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String deleteFollowerPost(@QueryParam(Const.PROJECT_ID) String projectId) {
        return deleteFollower(projectId);
    }

    @Path("/follower/delete")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public static String deleteFollower(@QueryParam(Const.PROJECT_ID) String projectId) {
        projectId = projectId.substring(2);
        JSONObject criteria = new JSONObject();
        criteria.put(InfocodeSchemeTable.PJ_ID, projectId);
        try {
            JSONObject re = CommonUtil.delete(false, HBaseTable.infocode_scheme_follower, criteria);
            return DpUtils.successJsonMsg("");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    @Path("scheme/info/create")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String createInfo(String jsonStr){
        JSONObject json = JSONObject.parseObject(jsonStr);
        try{
            String msg = this.verify(json);
            if(msg!=null){
                return msg;
            }
            JSONArray criterias = (JSONArray) json.get("criterias");
            InfoCodeUtil.format(criterias,true);
            JSONObject re = CommonUtil.insert(true,HBaseTable.infocode_scheme_detail,criterias);
            MessageHandler.publish(String.format("{\"type\":12,\"projectId\":\"\",\"dictId\":\"%s\",\"description\":\"\"}",json.getString("scheme_id")));
            JSONArray reContent = (JSONArray) re.get("Content");
            InfoCodeUtil.deFormat(reContent);
            return DpUtils.returnJSONArray(reContent,"");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    private String verify(JSONObject json) throws Exception {
        if (json.get(InfocodeSchemeTable.SCHEME_ID) == null) {
            return DpUtils.errorJsonMsg("missing key : " + InfocodeSchemeTable.SCHEME_ID);
        }
        String schemeId = (String) json.get(InfocodeSchemeTable.SCHEME_ID);
        String objType = (String) json.get(InfocodeSchemeTable.OBJ_TYPE);
        JSONObject queryJson = new JSONObject();
        queryJson.put(InfocodeSchemeTable.SCHEME_ID, schemeId);

        JSONObject re = null;
        re = CommonUtil.getCount(false, HBaseTable.infocode_scheme, queryJson);
        boolean isCtmId = false;
        if (re.getLongValue("Count") == 0) {
            if(!resourceContext.getResource(CtmDict.class).isExisted(schemeId)){
                return DpUtils.errorJsonMsg("Please create a scheme first! 请先创建信息点方案!");
            }
            isCtmId = true;
        }
        if(!isCtmId){
            HashSet<String> tmpSet = new HashSet<>(InfoCodeUtil.objTypeSet);
            EqStaticInfo eqStaticInfo = new EqStaticInfo(null);
            tmpSet.addAll(eqStaticInfo.getEcSet());
            tmpSet.addAll(eqStaticInfo.getEqSet());
            tmpSet.addAll(eqStaticInfo.getSysSet());
            if (objType == null || !InfoCodeUtil.checkRange(tmpSet, objType)) {
                return DpUtils.errorJsonMsg("illegal obj_type");
            }
        }else {
            HashSet<String> tmpSet = new HashSet<>();
            EqStaticInfo eqStaticInfo = new EqStaticInfo(schemeId, true);
            tmpSet.addAll(eqStaticInfo.getEcSet());
            tmpSet.addAll(eqStaticInfo.getEqSet());
            tmpSet.addAll(eqStaticInfo.getSysSet());
            tmpSet.addAll(eqStaticInfo.getFamilySet());
            if (objType == null || !InfoCodeUtil.checkRange(tmpSet, objType)) {
                return DpUtils.errorJsonMsg("illegal obj_type");
            }
        }
        JSONArray criterias = (JSONArray) json.get("criterias");
        CommonUtil.addField(criterias, InfocodeSchemeTable.SCHEME_ID, schemeId);
        CommonUtil.addField(criterias, InfocodeSchemeTable.OBJ_TYPE, objType);
        HashSet<String> infoPointCodeSet = new HashSet<>();
        for (int i = 0; i < criterias.size(); ++i) {
            JSONObject obj = (JSONObject) criterias.get(i);
            if(!isCtmId){
                if (obj.get("firstTag") == null || !InfoCodeUtil.checkRange(InfoCodeUtil.firstTagSet, obj.get("firstTag").toString())) {
                    return DpUtils.errorJsonMsg("illegal firstTag：" + obj.get("firstTag") + ", should be value from " + InfoCodeUtil.firstTagSet);
                }
            }
            String infoPointCode = (String) obj.get("infoPointCode");
            if (infoPointCode == null || infoPointCode.length() == 0) {
                return DpUtils.errorJsonMsg("illegal infoPointCode");
            }
            if (infoPointCodeSet.contains(infoPointCode)) {
                return DpUtils.errorJsonMsg("conflict infoPointCode : " + infoPointCode);
            }
            infoPointCodeSet.add(infoPointCode);
            if(!isCtmId) {
                if (!infoPointCode.startsWith(InfoCodeUtil.prefix)) {
                    infoPointCode = InfoCodeUtil.prefix + infoPointCode;
                    obj.put("infoPointCode", infoPointCode);
                }
            }
        }
        return null;
    }

    @Path("scheme/info/query")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String queryInfo(String jsonStr){
        JSONObject json = JSONObject.parseObject(jsonStr);
        JSONObject criteria = (JSONObject) json.get("criteria");
        InfoCodeUtil.format(criteria,false);
        try{
            JSONObject re = CommonUtil.query(false,HBaseTable.infocode_scheme_detail,criteria);
            if(!re.get("Result").equals("success")){
                return DpUtils.errorJsonMsg("查询出错");
            }
            JSONArray content = (JSONArray) re.get("Content");
            InfoCodeUtil.deFormat(content);
            InfoCodeUtil.sortByTag(content);
            return DpUtils.returnJSONArray(content,"");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    @Path("scheme/info/update")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String updateInfo(String jsonStr){
        JSONObject json = JSONObject.parseObject(jsonStr);
        JSONObject criteria = (JSONObject) json.get("criteria");
        JSONObject set = (JSONObject) json.get("set");
        String[] keys = {"scheme_id","obj_type","infoPointCode"};
        for(String key : keys){
            if(!criteria.containsKey(key))
                return DpUtils.errorJsonMsg("missing key : " + key);
        }
        InfoCodeUtil.format(criteria,false);
        InfoCodeUtil.format(set,false);
        if(set.containsKey("firstTag")){
            if(!InfoCodeUtil.checkRange(InfoCodeUtil.firstTagSet,set.get("firstTag").toString())){
                return DpUtils.errorJsonMsg("illegal firstTag");
            }
        }
        try{
            JSONObject re =CommonUtil.update(false,HBaseTable.infocode_scheme_detail,criteria,set);
            if(re.getLongValue("Count") == 0){
                return DpUtils.errorJsonMsg("要更新的数据不存在");
            }
            MessageHandler.publish(String.format("{\"type\":12,\"projectId\":\"\",\"dictId\":\"%s\",\"description\":\"\"}",criteria.getString("scheme_id")));
            return DpUtils.successJsonMsg("");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }

    @Path("scheme/info/delete")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public static String deleteInfo(String jsonStr){
        JSONObject json = JSONObject.parseObject(jsonStr);
        JSONObject criteria = (JSONObject) json.get("criteria");
        if(!criteria.containsKey(InfocodeSchemeTable.SCHEME_ID)){
            return DpUtils.errorJsonMsg("missing key : " + InfocodeSchemeTable.SCHEME_ID);
        }
        InfoCodeUtil.format(criteria,false);
        try{
            JSONObject re = CommonUtil.delete(false,HBaseTable.infocode_scheme_detail,criteria);
            MessageHandler.publish(String.format("{\"type\":12,\"projectId\":\"\",\"dictId\":\"%s\",\"description\":\"\"}",criteria.getString("scheme_id")));
            return DpUtils.successJsonMsg("");
        } catch (Exception e) {
            e.printStackTrace();
            return DpUtils.errorJsonMsg(Arrays.toString(e.getStackTrace()));
        }
    }


}
