package com.lingniu.ingest.protocol.jt808.downlink;

import com.lingniu.ingest.api.ProtocolId;
import com.lingniu.ingest.protocol.jt808.codec.BodyParserRegistry;
import com.lingniu.ingest.protocol.jt808.codec.Jt808Escape;
import com.lingniu.ingest.protocol.jt808.codec.Jt808MessageDecoder;
import com.lingniu.ingest.protocol.jt808.model.Jt808Body;
import com.lingniu.ingest.protocol.jt808.model.Jt808Message;
import com.lingniu.ingest.protocol.jt808.model.Jt808MessageId;
import com.lingniu.ingest.protocol.jt808.session.Jt808ChannelRegistry;
import com.lingniu.ingest.protocol.jt808.session.Jt808PendingRequests;
import com.lingniu.ingest.session.DeviceSession;
import com.lingniu.ingest.protocol.jt808.TestSessionStore;
import io.netty.buffer.ByteBuf;
import io.netty.channel.embedded.EmbeddedChannel;
import org.junit.jupiter.api.Test;

import java.nio.ByteBuffer;
import java.time.Instant;
import java.util.List;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

class Jt808CommandDispatcherTest {

    @Test
    void notifyWritesSubpackageFramesForLargeBody() {
        TestSessionStore sessions = new TestSessionStore();
        sessions.put(new DeviceSession("sid-1", ProtocolId.JT808, "LNVIN000000000303",
                "123456789012", "", "127.0.0.1:10000", Instant.now(), Instant.now(), Map.of()));
        Jt808ChannelRegistry channels = new Jt808ChannelRegistry();
        EmbeddedChannel channel = new EmbeddedChannel();
        channels.bind("123456789012", channel);
        Jt808CommandDispatcher dispatcher = new Jt808CommandDispatcher(
                sessions, channels, new Jt808PendingRequests());
        byte[] body = new byte[2048];

        dispatcher.notify("sid-1", new Jt808Commands.DownlinkCommand(
                Jt808MessageId.PLATFORM_SET_PARAMS, body)).join();

        Jt808MessageDecoder decoder = new Jt808MessageDecoder(new BodyParserRegistry(List.of()));
        for (int i = 1; i <= 3; i++) {
            ByteBuf outbound = channel.readOutbound();
            byte[] frame = new byte[outbound.readableBytes()];
            outbound.readBytes(frame);
            byte[] unescaped = Jt808Escape.unescape(frame, 1, frame.length - 2);
            Jt808Message decoded = decoder.decode(ByteBuffer.wrap(unescaped));
            assertThat(decoded.header().subpacket()).isTrue();
            assertThat(decoded.header().totalPackets()).isEqualTo(3);
            assertThat(decoded.header().packetSeq()).isEqualTo(i);
            assertThat(decoded.body()).isInstanceOf(Jt808Body.Raw.class);
        }
        assertThat((Object) channel.readOutbound()).isNull();
    }
}
