package com.pwt.netty.handler.codec.vehicle2;

import com.pwt.common.constant.LogConstants;
import com.pwt.netty.common.vehicle2.client.*;
import com.pwt.netty.common.vehicle2.server.*;
import com.pwt.netty.common.vehicle2.Vehicle2Message;
import com.pwt.netty.handler.codec.exceptions.ProtocolException;
import com.pwt.netty.util.MessageUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteOrder;

import static com.pwt.netty.common.vehicle2.Vehicle2Message.MAGIC_LENGTH;

@Slf4j(topic = LogConstants.VEHICLE_BIZ)
public class Vehicle2ProtocolDecoder extends LengthFieldBasedFrameDecoder {

    public Vehicle2ProtocolDecoder() {
        super(ByteOrder.LITTLE_ENDIAN, 1024, 3, 2, -5, 3, true);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        if (in != null) {
            log.info("原始报文：{}", MessageUtil.convertByteBufToString(in));
        }
        if (in.readableBytes() < MAGIC_LENGTH) {
            return null;
        }

        // 验证frame header
        in.markReaderIndex();
        int header = in.readUnsignedMedium();
        if (header != Vehicle2Message.MAGIC) {
            throw new ProtocolException(String.format("invalid frame header %x", header));
        }
        in.resetReaderIndex();

        // 基于长度帧解码
        ByteBuf byteBuf = (ByteBuf) super.decode(ctx, in);
        if (byteBuf == null) {
            return null;
        }

        int readableBytes = byteBuf.readableBytes();
        int lengthFieldValue = byteBuf.readUnsignedShortLE();

        if(byteBuf.getByte(readableBytes - 1) != Vehicle2Message.MAGIC_END) {
            throw new ProtocolException("invalid frame end");
        }

        byte type = byteBuf.readByte();

        Vehicle2Message message;
        switch (type) {
            case (byte)0x01:
                message = new PowerSendRequest();
                break;
            case (byte)0x02:
                message = new PowerSendResponse();
                break;
            case (byte)0x03:
                message = new HeartBeatRequest();
                break;
            case (byte)0x04:
                message = new HeartBeatResponse();
                break;
            case (byte)0x05:
                message = new LockRequest();
                break;
            case (byte)0x06:
                message = new LockResponse();
                break;
            case (byte)0x07:
                message = new UnlockRequest();
                break;
            case (byte)0x08:
                message = new UnlockResponse();
                break;
            case (byte)0x09:
                message = new SettlementRequest();
                break;
            case (byte)0x10:
                message = new SettlementResponse();
                break;
            case (byte)0x11:
                message = new SetParamRequest();
                break;
            case (byte)0x12:
                message = new SetParamResponse();
                break;
            default:
                throw new ProtocolException(String.format("invalid message type 0x%x.", type));
        }
        if (message.getProtocolLength() != lengthFieldValue) {
            throw new ProtocolException("decode frame error: data length mismatched.");
        }
        message.decode(byteBuf);
        return message;
    }
}
