package com.gyee.dataadapter.config;

import cn.hutool.core.date.DateUtil;
import com.gyee.dataadapter.cache.MqttCache;
import com.gyee.dataadapter.entity.PointData;
import lombok.Data;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Date;

/**
 * 数据转换工具
 */
@Data
public class DataConverterManager2 {
    /**
     * 序号
     */
    private int index = 0;
    private byte[] datas;
    /**
     * 版本号
     */
    private String version = "";
    /**
     * 点位数量
     */
    private int pointCount = 0;
    /**
     * 压缩算法
     */
    private byte zipType;

    //private List<PointData> pintInfos = new ArrayList<>();

    public DataConverterManager2(byte[] bs) {
        datas = bs;

        // 初始化
        init();

    }

    private void init() {
        // 消息头，版本号数量
        //version = getString(4);
        index += 4;
        // 点位数量
        //pointCount = getInt();
        index += 4;

        //zipType = getByte();
        index += 1;

        initPoint();
    }

    /**
     * 初始化内容
     */
    private void initPoint() {
        while (index < datas.length) {
            getPointInfo();
            pointCount++;
        }
    }

    private void getPointInfo() {
        PointData pi = new PointData();
        // 数据源
        //byte source = getByte();
        index += 1;
        //pi.setSource(source);
        // 点名长度
        int pnameLen = getUshort();
        String pname = getString(pnameLen);
        pi.setTagName(pname);
        // 值类型
        byte vtype = getByte();
        //pi.setValueType(vtype);
        int vlen = 0;
        if (vtype == 0 || vtype == 254) {
            // 值长度
            vlen = getUshort();
        }
        // 获取的实际值
        setValueByType(pi, vtype, vlen);
        // 时间戳
        //        long ts = getLong();
        //        pi.setTime(ts);
        //时间戳转为时间
        pi.setTime(getDate());
        // 状态码
        //int status = getInt();
        index += 4;
        // 质量位
        //byte q = getByte();
        index += 1;

        MqttCache.subData2.put(pname, pi);
    }

    /**
     * 获取实际值
     *
     * @param pi
     * @param vtype 值类型
     * @param vlen  值长度
     * @return 实际值
     */
    private void setValueByType(PointData pi, byte vtype, int vlen) {
        switch (vtype) {
            case 0:
                pi.setDoubleValue(Double.parseDouble(getString(vlen)));
                break;
            case 1:
                pi.setBooleanValue(getBool());
                break;
            case 2:
                pi.setLongValue(getUshort());
                break;
            case 3:
                pi.setLongValue(getInt());
                break;
            case 4:
                pi.setLongValue(getLong());
                break;
            case 5:
                pi.setDoubleValue(getFloat());
                break;
            case 6:
                pi.setDoubleValue(getDouble());
                break;
            case 7:
                pi.setDoubleValue(Double.parseDouble(getString(vlen)));
                break;
            case 8:
                pi.setLongValue(getUshort());
                break;
            case 9:
                pi.setLongValue(getInt());
                break;
            case 10:
                pi.setLongValue(getLong());
                break;
            case 11:
                pi.setDoubleValue(Double.parseDouble(getString(vlen)));
                break;
        }
    }

    private double getDouble() {
        int count = 8;
        byte[] bs = Arrays.copyOfRange(datas, index, count + index);
        toReverserBytes(bs);
        float val = ByteBuffer.wrap(bs).getFloat();
        index += count;

        return val;
    }

    private double getFloat() {
        int count = 4;
        byte[] bs = Arrays.copyOfRange(datas, index, count + index);
        toReverserBytes(bs);
        float val = ByteBuffer.wrap(bs).getFloat();

        index += count;

        return val;
    }

    private long getLong() {
        int count = 8;
        byte[] bs = Arrays.copyOfRange(datas, index, count + index);
        toReverserBytes(bs);
        long val = ByteBuffer.wrap(bs).getLong();
        val /= 10000;

        index += count;
        return val;
    }

    private Date getDate() {
        int count = 8;
        byte[] bs = Arrays.copyOfRange(datas, index, count + index);
        toReverserBytes(bs);
        long val = ByteBuffer.wrap(bs).getLong();
        val /= 10000;

        index += count;
        return new Date(val);
    }


    private boolean getBool() {
        byte b = getByte();
        return b != 0;
    }


    private int getInt() {
        int count = 4;
        byte[] bs = Arrays.copyOfRange(datas, index, count + index);
        toReverserBytes(bs);
        int val = ByteBuffer.wrap(bs).getInt();

        index += count;

        return val;
    }

    private short getUshort() {
        int count = 2;
        byte[] bs = Arrays.copyOfRange(datas, index, count + index);

        //toReverserBytes(bs);
        short ushortValue = (short) ((bs[0] & 0xFF) | ((bs[1] & 0xFF) << 8));

        index += count;

        return ushortValue;
    }

    private String getString(int count) {
        String str = new String(Arrays.copyOfRange(datas, index, count + index), StandardCharsets.UTF_8);

        index += count;

        return str;
    }

    private byte getByte() {
        int count = 1;
        byte[] bs = Arrays.copyOfRange(datas, index, count + index);

        index += count;

        return bs[0];
    }

    private void toReverserBytes(byte[] bytes) {
        for (int i = 0; i < bytes.length / 2; i++) {
            byte temp = bytes[i];
            bytes[i] = bytes[bytes.length - 1 - i];
            bytes[bytes.length - 1 - i] = temp;
        }
    }

}
