package com.cisdi.data.AMETEKSurfaceVision.gateway;

import com.alibaba.fastjson.JSON;
import com.cisdi.data.AMETEKSurfaceVision.DynamicCodeActionParamDTO.PropertyConfig;
import com.cisdi.data.AMETEKSurfaceVision.DynamicCodeActionParamDTO.PropertyType;
import com.cisdi.data.common.exception.BusinessException;
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.BeanUtils;

/**
 * 表检仪解码
 *
 * @author zhongda
 */
public class SurfaceVisionVoDecoder {
    /** 将消息头和消息体拆包，解析出消息头信息 */
    public static SurfaceVisionFrameInputVo Decode(ByteBuf in) {
        SurfaceVisionFrameInputVo vo = new SurfaceVisionFrameInputVo();
        //消息体部分
        int length;
        if (in == null) {
            throw new BusinessException("ByteBuf 入参为null");
        } else if (in.readableBytes() > 4) {
            length = in.readableBytes();
        }
        else {
            throw new BusinessException("报文长度不匹配 ,期望：大于4，实际：" + in.readableBytes());
        }
        //去掉结束符
        byte[] headerBytes = new byte[length - 4];
        in.readBytes(headerBytes);

        //将数据流转为字符串，UTF_8编码
        String strData = new String(headerBytes, StandardCharsets.UTF_8);

        //以分隔符分割数据
        List<String> data = Arrays.asList(strData.split(SurfaceVisionConstants.SEPARATE1, -1));

        //获取报文头
        vo.setMsgKey(data.get(0));

        //去掉报文头
        vo.setData(data.subList(1, data.size()));

        //判断是否为心跳帧
        byte[] header = data.get(0).getBytes(StandardCharsets.UTF_8);
        if (header.length == 1 && header[0] == SurfaceVisionConstants.BEAT_BYTE){
            vo.setBeatType(true);
        }
        return vo;
    }

    /** 非Query命令正常返回消息解码 */
    public static void DecodeReturn(SurfaceVisionFrameInputVo vo) {
        List<String> data = vo.getData();
        if (data.size() < SurfaceVisionConstants.MIN_NORMAL_RETURN){
            throw new BusinessException("返回消息不标准，msg：" + JSON.toJSONString(data));
        }

        vo.setReplayId(Integer.valueOf(data.get(0)));
        vo.setStatus(SurfaceVisionConstants.RETURN_OK.equalsIgnoreCase(data.get(1)));
        vo.setDescription(data.get(2));
    }

    /** 命令异常返回消息解码 */
    public static void DecodeReturnError(SurfaceVisionFrameInputVo vo) {
        List<String> data = vo.getData();
        int size = data.size();
        if (size < SurfaceVisionConstants.MIN_NORMAL_RETURN){
            throw new BusinessException("返回消息不标准，msg：" + JSON.toJSONString(data));
        }

        StringBuffer message = new StringBuffer();
        message.append(data.get(size - 1))
            .append(":")
            .append(data.get(size - 2));

        vo.setReplayId(0);
        vo.setStatus(false);
        vo.setDescription(message.toString());
    }

    /** Query命令返回消息解码 */
    public static void DecodeReturnQuery(SurfaceVisionFrameInputVo vo) {
        List<String> data = vo.getData();
        int size = data.size();
        if (size < 2){
            throw new BusinessException("返回查询消息不标准，msg：" + JSON.toJSONString(data));
        }

        Map<String, Object> queryData = new HashMap<>();
        queryData.put("result", data.get(size - 1));

        vo.setReplayId(0);
        vo.setStatus(true);
        vo.setReturnData(queryData);
    }

    /** 上送消息解码 */
    public static void DecodeData(SurfaceVisionFrameInputVo vo, List<PropertyConfig> propertyConfigs) {
        List<String> data = vo.getData();

        //判断上送消息字段数是否与点位配置信息字段数一致
        if (data.size() != propertyConfigs.size()){
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append("报文数据字段数与点位配置不一致 ,电文ID：")
                .append(vo.getMsgKey())
                .append("，电文字段数：")
                .append(data.size())
                .append(", 点位字段数：")
                .append(propertyConfigs.size());
            throw new BusinessException(stringBuffer.toString());
        }

        Map<String, Object> valueMap = new HashMap<>();

        //按照点位配置字段顺序获取上送信息
        for (int i = 0; i < data.size(); i++){
            String value = data.get(i);
            PropertyConfig propertyConfig = propertyConfigs.get(i);

            PropertyType propertyType = propertyConfig.getPropertyType();

            String propertyId = propertyConfig.getPropertyId();

            formatValue(valueMap, value, propertyType, propertyId);
        }

        vo.setReturnData(valueMap);
    }

    /** 更具字段类型格式化数据值 */
    private static void formatValue(Map<String, Object> valueMap, String value, PropertyType propertyType, String propertyId) {
        switch (propertyType){
            case INT: {
                valueMap.put(propertyId, Integer.valueOf(value));
                break;
            }
            case BYTE: {
                valueMap.put(propertyId, Byte.valueOf(value));
                break;
            }
            case BOOLEAN: {
                valueMap.put(propertyId, Boolean.valueOf(value));
                break;
            }
            case SHORT: {
                valueMap.put(propertyId, Short.valueOf(value));
                break;
            }
            case FLOAT: {
                valueMap.put(propertyId, Float.valueOf(value));
                break;
            }
            case DOUBLE: {
                valueMap.put(propertyId, Double.valueOf(value));
                break;
            }
            case LONG: {
                valueMap.put(propertyId, Long.valueOf(value));
                break;
            }
            default:{
                valueMap.put(propertyId, value);
                break;
            }
        }
    }

    public static void main(String[] args) throws Exception {
        //标签读取
        SurfaceVisionFrameDecoder surfaceVisionFrameDecoder = new SurfaceVisionFrameDecoder();
//        String str = "DEFECT|1|3|2011-03-19 15:21:45|2.54|1.73|252.76|$\r\n";
        //粘包
        String str = "DEFECT|1|3|2011-03-19 15:21:45||1.23||$\r\nDEFECT|1|3|2011-03-19 15:21:45||1.23||";
//        String str = "DEFECT|1|3|2011-03-19 15:21:45|2.54|1.73|252.76|$\r\n";
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        ByteBuf copiedBuff = Unpooled.copiedBuffer(bytes);
        List<Object> out = new ArrayList<Object>();
        surfaceVisionFrameDecoder.decode(null, copiedBuff, out);

        ByteBuf bufferIn = (ByteBuf) out.get(0);

        SurfaceVisionFrameInputVo vo = Decode(bufferIn);
        String msgKey = vo.getMsgKey();

        SocketReturnMessage returnMsg = new SocketReturnMessage();
        returnMsg.setMsgKey("1");
        returnMsg.setMsgId("2");
        returnMsg.setData(new byte[3]);

        SurfaceVisionSocketReturnMessage sendMsg = new SurfaceVisionSocketReturnMessage();
        BeanUtils.copyProperties(returnMsg, sendMsg);

        sendMsg.setSendReturnFlag(true);

        String msgKey1 = "test";
        Map<String, Object> propsMap = new HashMap<>();
        propsMap.put("id1", 1);
        propsMap.put("id2", 2.33);
        propsMap.put("id3", "value");
        List<PropertyConfig> propertyConfigList = new ArrayList<>();
        PropertyConfig propertyConfig1 = new PropertyConfig();
        propertyConfig1.setPropertyId("id1");
        propertyConfigList.add(propertyConfig1);
        PropertyConfig propertyConfig2 = new PropertyConfig();
        propertyConfig2.setPropertyId("id2");
        propertyConfigList.add(propertyConfig2);
        PropertyConfig propertyConfig3 = new PropertyConfig();
        propertyConfig3.setPropertyId("id3");
        propertyConfigList.add(propertyConfig3);
        int count = 1;

        SurfaceVisionEncoder.Encode(msgKey1, propsMap, propertyConfigList, count);
    }


}
