package com.skr.mdm.netty;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ByteUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.digest.DigestUtil;
import com.skr.mdm.enums.MdmEncryptEnum;
import com.skr.mdm.util.SmUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteOrder;

/**
 * @author nfq
 * @date 2020/7/28 18:35
 */
@Slf4j
public class WebsocketEncoder {


    public static ByteBuf encoder(short type, String body, String mdmEncrypt) {
        if (MdmEncryptEnum.SM.getMdmEncrypt().equals(mdmEncrypt)) {
            return encoderBySm(type, body);
        } else {
            return encoderByMd5(type, body);
        }
    }

    public static ByteBuf encoderByMd5(short type, String body) {
        String sign = DigestUtil.md5Hex(body);
        byte[] typeBytes = Convert.shortToBytes(type);
        byte[] signBytes = sign.getBytes();
        byte[] bodyBytes = body.getBytes();
        byte[] lengthBytes = Convert.intToBytes(bodyBytes.length);

        byte[] bytes = new byte[typeBytes.length + lengthBytes.length + signBytes.length + bodyBytes.length];
        int len = 0;
        System.arraycopy(typeBytes, 0, bytes, 0, typeBytes.length);
        len += typeBytes.length;
        System.arraycopy(lengthBytes, 0, bytes, len, lengthBytes.length);
        len += lengthBytes.length;
        System.arraycopy(signBytes, 0 , bytes, len, signBytes.length);
        len += signBytes.length;
        System.arraycopy(bodyBytes, 0, bytes, len, bodyBytes.length);

        ByteBuf byteBuf = Unpooled.directBuffer(bytes.length);
        byteBuf.writeBytes(bytes);
        return byteBuf;
    }


    public static ByteBuf encoderBySm(short type, String body) {
        String sm3 = SmUtil.sm3(body);
        SM2 sm2 = SmUtils.sm2Sign();
        String signHex = sm2.signHex(sm3);

        byte[] typeBytes = ByteUtil.shortToBytes(type, ByteOrder.BIG_ENDIAN);
        byte[] signBytes = HexUtil.decodeHex(signHex);
        byte[] bodyBytes = body.getBytes();
        byte[] lengthBytes = ByteUtil.intToBytes(bodyBytes.length, ByteOrder.BIG_ENDIAN);

        byte[] bytes = new byte[typeBytes.length + lengthBytes.length + signBytes.length + bodyBytes.length];
        int len = 0;
        System.arraycopy(typeBytes, 0, bytes, 0, typeBytes.length);
        len += typeBytes.length;
        System.arraycopy(lengthBytes, 0, bytes, len, lengthBytes.length);
        len += lengthBytes.length;
        System.arraycopy(signBytes, 0 , bytes, len, signBytes.length);
        len += signBytes.length;
        System.arraycopy(bodyBytes, 0, bytes, len, bodyBytes.length);

        ByteBuf byteBuf = Unpooled.directBuffer(bytes.length);
        byteBuf.writeBytes(bytes);
        return byteBuf;
    }
}
