package com.persagy.dmp.rwd.iot.service.impl;

import cn.hutool.core.io.IORuntimeException;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.dmp.basic.model.QueryCriteria;
import com.persagy.dmp.basic.utils.QueryCriteriaHelper;
import com.persagy.dmp.common.context.AppContext;
import com.persagy.dmp.digital.entity.ObjectDigital;
import com.persagy.dmp.mybatis.utils.ConditionUtil;
import com.persagy.dmp.rwd.basic.constant.IotUrlConstant;
import com.persagy.dmp.rwd.basic.utils.MeterUtils;
import com.persagy.dmp.rwd.digital.service.IObjectDigitalService;
import com.persagy.dmp.rwd.iot.model.CurrentDataModel;
import com.persagy.dmp.rwd.iot.service.CurrentIotService;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


/**
 * iot-查询实时数据
 * @author:linhuili
 * @date:2021/8/11
 */
@Service
public class CurrentIotServiceImpl implements CurrentIotService {

    @Autowired
    private IObjectDigitalService objectDigitalService;

    @Value("${persagy.iot.data.server}")
    private String iotDataServer;


    /**
     * 查询对象绑点信息点的实时数据
     * @param param
     * @return
     */
    @Override
    public List<CurrentDataModel> getCurrentData(List<CurrentDataModel> param) throws Exception{
        if(param == null || param.size()<=0){
            return new ArrayList<>();
        }
        //表号功能号校验
        List<PointParam> parameters = verifyMeterAndFunction(param);
        if (parameters.size() == 0) {
            return param;
        }

        //查询实时数据
        String url = iotDataServer + IotUrlConstant.QUERY_CUCCRENT_DATA;
        JSONObject requestBody = new JSONObject();
        requestBody.put("building", AppContext.getContext().getProjectId().substring(2));
        requestBody.put("points", parameters);

        String response = null;
        try{
            //处理iot-collect 请求返回超时
            response = HttpUtil.post(url, requestBody.toString(), 3000);
        }catch (IORuntimeException e){
            e.printStackTrace();
            return param;
        }
        //处理iot-collect 未部署情况
        if(response.contains("<html>")){
            return param;
        }
        JSONObject result = JSONObject.parseObject(response);
        if(result == null){
            return param;
        }
        JSONArray points = result.getJSONArray("points");
        //绑定表号功能号
        for (Object object : points) {
            JSONObject item = (JSONObject) object;
            String meter = item.getString("meter");
            String funcid = item.getString("funcid");
            for (CurrentDataModel model : param) {
                if (meter.equals(model.getMeter()) && funcid.equals(model.getFunction())) {
                    model.setData(item.get("data"));
                    model.setTime(item.getString("receivetime"));
                }
            }
        }
        return param;
    }


    /**
     * 校验表号功能号
     * @param param
     */
    private List<PointParam> verifyMeterAndFunction(List<CurrentDataModel> param){
        List<PointParam> parameters = new LinkedList<>();
        for (CurrentDataModel model : param) {
            if (model.getObjectId() == null) {
                model.setError("对象id不可为空");
                continue;
            }
            String infoCode = model.getInfoCode();
            if (infoCode == null) {
                model.setError("信息点编码不可为空");
                continue;
            }
            //校验表号功能号是否存在
            String infoCodeValue = getInfoCodeValue(model.getObjectId(), infoCode);
            if(StringUtils.isEmpty(infoCodeValue)){
                model.setError("value of infoCode[" + model.getObjectId() + ":" + infoCode + "] is null");
                continue;
            }
            // 判断信息点的值是不是表号-功能号格式
            model.setInfoValue(infoCodeValue);
            if (!MeterUtils.matchFormat(infoCodeValue)) {
                model.setError("value of infoCode[" + model.getObjectId() + ":" + infoCode + "][ " + infoCodeValue + "] 不是正确的表号功能号");
                continue;
            }
            parameters.add(new PointParam(model.getMeter(), model.getFunction()));
        }
        return parameters;
    }


    /**
     * 查询信息点值
     * @param objectId
     * @param infoCode
     * @return
     * @throws Exception
     */
    public String getInfoCodeValue(String objectId,String infoCode){
        //查询条件封装
        QueryCriteria queryCriteria = new QueryCriteria();
        ObjectNode criteria = JsonNodeFactory.instance.objectNode();
        criteria.put("id",objectId);
        criteria.put("valid",1);
        queryCriteria.setCriteria(criteria);

        //查询object对象
        QueryWrapper<ObjectDigital> wrapper = new QueryWrapper<>();
        // 添加所属项目条件
        ConditionUtil.ensureProjectCriteriaDirectly(wrapper);
        // 转换查询条件
        QueryCriteriaHelper.toWrapper(wrapper,queryCriteria, ObjectDigital.class);
        List<ObjectDigital> data = objectDigitalService.queryByCondition(wrapper);

        if(data == null || data.size()<=0){
            return null;
        }
        if("classCode".equals(infoCode)){
            return data.get(0).getClassCode();
        }
        ObjectNode jsonNodes = data.get(0).getInfos();
        if(jsonNodes.has(infoCode)){
            return jsonNodes.get(infoCode).textValue();
        }
        return null;
    }

    /**
     * 信息点参数定义
     */
    @Getter
    @Setter
    public static class PointParam {
        String meter;
        String funcid;

        public PointParam(String meter, String function) {
            this.meter = meter;
            this.funcid = function;
        }
    }
}

