package com.sagacloud.endpoints;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sagacloud.endpointService.CalendarService;
import com.sagacloud.endpoints.item.PhysicalObject;
import com.sagacloud.utils.DpUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import java.util.*;

/**
 * Created by wo on 7/9/19.
 */
@Path("calendar")
public class Calendar {
    @Context
    private ResourceContext resourceContext;

    private CalendarService calendarService = new CalendarService();

    @Path("/create")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public  String create(String jsonStr) throws Exception {
        return this.calendarService.create(jsonStr);
    }

    @Path("/create_from")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public  String createFrom(String jsonStr) throws Exception {
        return this.calendarService.createFrom(jsonStr);
    }

    @Path("/update")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public  String update(String jsonStr) throws Exception {
        return this.calendarService.update(jsonStr);
    }

    @Path("/delete")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public  String del(String jsonStr) throws Exception {
        return this.calendarService.del(jsonStr);
    }

    @Path("/query")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public  String query() throws Exception {
        return this.calendarService.query();
    }

    @Path("/create_rules")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String createRules(String jsonStr) throws Exception{
        return this.calendarService.createRules(jsonStr);
    }

    @Path("/del_rules")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String delRules(String jsonStr) throws Exception{
        return this.calendarService.delRules(jsonStr);
    }

    @Path("/update_rule")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String updateRule(String jsonStr) throws Exception{
        return this.calendarService.updateRule(jsonStr);
    }

    @Path("/query_rules")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String queryRules(String jsonStr) throws Exception{
        return this.calendarService.queryRules(jsonStr);
    }

    @Path("/set_tags")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String setTags(String jsonStr) throws Exception {
        /*String checkRe = this.checkTags(jsonStr);
        if(checkRe != null){
            return checkRe;
        }*/
        return this.calendarService.setTags(jsonStr);
    }

    /**对tag设置相关输入做合法性检查
     * @param jsonStr
     * @return
     */
    private String checkTags(String jsonStr){

        JSONArray dictContent = JSONObject.parseObject(resourceContext.getResource(Dictionary.class).queryCalendarTag()).getJSONArray("Content");
        Set<String> tags = new HashSet<>();
        dictContent.forEach(o -> {
            ((JSONObject)o).getJSONArray("content").forEach(o2 -> {
                tags.add(((JSONObject)o2).getString("code"));
            });
        });
        JSONArray arr = JSONObject.parseObject(jsonStr).getJSONArray("tags");
        for(int i = 0; i < arr.size(); i++){
            if(!tags.contains(arr.getJSONObject(i).getString("tag"))){
                return DpUtils.errorJsonMsg("tag值错误！");
            }
        }
        return null;
    }

    @Path("/unset_tags")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String unsetTags(String jsonStr) throws Exception {
        /*String checkRe = this.checkTags(jsonStr);
        if(checkRe != null){
            return checkRe;
        }*/
        return this.calendarService.unsetTags(jsonStr);
    }

    @Path("/set_intervals")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String setItvs(String jsonStr) throws Exception {
        String checkRe = this.checkIntervals(jsonStr);
        if(checkRe != null){
            return checkRe;
        }
        return this.calendarService.setItvs(jsonStr);
    }

    @Path("/set_intervals_by_tag")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String setInvByTag(String jsonStr) throws Exception {
        String[] keys = {"id", "query", "set_interval"};
        JSONObject json = JSONObject.parseObject(jsonStr);
        for(String key : Arrays.asList(keys)){
            if(!json.containsKey(key)){
                return DpUtils.errorJsonMsg("Missing key: " + key);
            }
        }
        String tag = json.getJSONObject("query").getString("tag");
        JSONObject qBody = new JSONObject().fluentPut("id", json.get("id")).fluentPut("tags", new JSONArray()
                .fluentAdd(tag)).fluentPut("dates", json.getJSONObject("query").get("dates"));
        JSONArray reContent = JSONObject.parseObject(this.queryDetails(qBody.toString())).getJSONArray("Content");
        List<JSONObject> toDels = new ArrayList<>();
        for(int i = 0; i < reContent.size(); i++){
            JSONObject item = reContent.getJSONObject(i);
            if(!item.getJSONArray("tags").toJavaList(String.class).contains(tag)){
                toDels.add(item);
            }
        }
        toDels.forEach(item -> reContent.remove(item));
        if(reContent.size() == 0){
            return DpUtils.successJsonMsg("");
        }
        JSONArray dateArr = new JSONArray();
        for(int i = 0; i < reContent.size(); i++){
            String dateStr= reContent.getJSONObject(i).getString("date");
            dateArr.add(new JSONObject().fluentPut("from", dateStr).fluentPut("to", dateStr));
        }
        JSONObject interval = json.getJSONObject("set_interval").fluentPut("dates", dateArr);
        JSONObject setBody = new JSONObject().fluentPut("id", json.get("id")).fluentPut("intervals", new JSONArray().fluentAdd(interval));
        return this.setItvs(setBody.toString());
    }

    @Path("/unset_intervals")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String unsetItvs(String jsonStr) throws Exception {
        String checkRe = this.checkIntervals(jsonStr);
        if(checkRe != null){
            return checkRe;
        }
        return this.calendarService.unsetItvs(jsonStr);
    }

    /**对interval设置相关输入做合法性检查
     * @param jsonStr
     * @return
     */
    private String checkIntervals(String jsonStr){
        JSONArray dictContent = JSONObject.parseObject(resourceContext.getResource(Dictionary.class).queryCalendarInterval()).getJSONArray("Content");
        Set<String> codes = new HashSet<>();
        dictContent.forEach(o -> {
            codes.add(((JSONObject)o).getString("code"));
        });
        JSONArray arr = JSONObject.parseObject(jsonStr).getJSONArray("intervals");
        for(int i = 0; i < arr.size(); i++){
            if(!codes.contains(arr.getJSONObject(i).getString("code"))){
                return DpUtils.errorJsonMsg("code值错误！");
            }
        }
        return null;
    }

    @Path("/query_details")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String queryDetails(String jsonStr) throws Exception {
        JSONObject input = JSONObject.parseObject(jsonStr);
        if(input.get("tags") == null && input.get("intervals") == null){
            return DpUtils.errorJsonMsg("tags 和 intervals必须有一项非空");
        }
        return this.calendarService.queryDetails(jsonStr);
    }

    @Path("/query_details_by_obj")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String queryDetailsByObj(String jsonStr) throws Exception {
        JSONObject input = JSONObject.parseObject(jsonStr);
        String objId = input.getString("id");
        if(!objId.startsWith("Sp") && !objId.startsWith("Sh") && !objId.startsWith("Fl") && !objId.startsWith("Bd") && !objId.startsWith("Pj")){
            return DpUtils.errorJsonMsg("必须是空间、竖井、楼层、建筑或项目id");
        }
        String calId = this.getCalId(objId);
        if(calId == null){
            return DpUtils.errorJsonMsg("对象未设置工作历，需配置在RelatedSchedule信息点上");
        }
        input.put("id", calId);
        if(input.get("tags") == null && input.get("intervals") == null){
            return DpUtils.errorJsonMsg("tags 和 intervals必须有一项非空");
        }
        return this.calendarService.queryDetails(input.toString());
    }

    /**查询对象RelatedSchedule信息点
     * @param objId
     * @return
     */
    private String getCalId(String objId){
        JSONObject body = JSONObject.parseObject(String.format("{\"criterias\":[{\"id\":\"%s\"}]}", objId));
        String pjId = "Pj" + objId.substring(2, 12);
        JSONArray dictContent = JSONObject.parseObject(resourceContext.getResource(PhysicalObject.class).batchQueryById(pjId, body)).getJSONArray("Content");
        if(dictContent.size() == 0){
            return null;
        }
        String calId = dictContent.getJSONObject(0).getJSONObject("infos").getString("RelatedSchedule");
        if(calId != null && !calId.isEmpty()){
            return calId;
        }
        if(objId.startsWith("Pj")){
            return null;
        }
        JSONObject loc = dictContent.getJSONObject(0).getJSONObject("location");
        JSONArray arr = new JSONArray();
        if(loc != null && loc.getString("floor") != null){
            arr.add(JSONObject.parseObject(String.format("{\"id\":\"%s\"}", loc.getString("floor"))));
        }
        if(loc != null && loc.getString("building") != null){
            arr.add(JSONObject.parseObject(String.format("{\"id\":\"%s\"}", loc.getString("building"))));
        }
        arr.add(JSONObject.parseObject(String.format("{\"id\":\"%s\"}", pjId)));
        dictContent = JSONObject.parseObject(resourceContext.getResource(PhysicalObject.class).batchQueryById(pjId, body.fluentPut("criterias", arr))).getJSONArray("Content");
        String flCalId = null, bdCalId = null, pjCalId = null;
        for(int i = 0; i < dictContent.size(); i++){
            JSONObject entry = dictContent.getJSONObject(i);
            String tmpId = entry.getJSONObject("infos").getString("RelatedSchedule");
            if(entry.getString("id").startsWith("Fl")){
                flCalId = tmpId;
            }
            if(entry.getString("id").startsWith("Bd")){
                bdCalId = tmpId;
            }
            if(entry.getString("id").startsWith("Pj")){
                pjCalId = tmpId;
            }
        }
        return flCalId != null? flCalId : bdCalId != null? bdCalId : pjCalId;
    }

}
