import "should";
import { appendChecksumFooter } from "../helpers";
import { parseNmeaSentence, GSVPacket } from "../index";

describe("GSV", (): void => {
    it("parses GPS satellites correctly", (): void => {
        const packet = parseNmeaSentence("$GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74") as GSVPacket;

        packet.should.have.property("sentenceId", "GSV");
        packet.should.have.property("talkerId", "GP");
        packet.should.have.property("numberOfMessages", 3);
        packet.should.have.property("messageNumber", 1);
        packet.should.have.property("satellitesInView", 11);

        packet.satellites.should.be.instanceof(Array).and.have.lengthOf(4);
        packet.satellites[0].should.deepEqual({
            prnNumber: 3,          // GPS PRN (no offset)
            elevationDegrees: 3,
            azimuthTrue: 111,
            SNRdB: 0
        });
        packet.satellites[1].should.deepEqual({
            prnNumber: 4,
            elevationDegrees: 15,
            azimuthTrue: 270,
            SNRdB: 0
        });
        packet.satellites[2].should.deepEqual({
            prnNumber: 6,
            elevationDegrees: 1,
            azimuthTrue: 10,
            SNRdB: 0
        });
        packet.satellites[3].should.deepEqual({
            prnNumber: 13,
            elevationDegrees: 6,
            azimuthTrue: 292,
            SNRdB: 0
        });
    });

    it("parses Galileo satellites correctly", (): void => {
        const sentence = appendChecksumFooter("$GAGSV,3,1,09,02,15,208,35,03,71,344,32,08,41,147,33,11,25,233,34");
        const packet = parseNmeaSentence(sentence) as GSVPacket;

        packet.should.have.property("sentenceId", "GSV");
        packet.should.have.property("talkerId", "GA");
        packet.should.have.property("numberOfMessages", 3);
        packet.should.have.property("messageNumber", 1);
        packet.should.have.property("satellitesInView", 9);

        packet.satellites.should.be.instanceof(Array).and.have.lengthOf(4);
        packet.satellites[0].should.deepEqual({
            prnNumber: 102,        // Galileo PRN (offset by +100)
            elevationDegrees: 15,
            azimuthTrue: 208,
            SNRdB: 35
        });
        packet.satellites[1].should.deepEqual({
            prnNumber: 103,        // Galileo PRN (offset by +100)
            elevationDegrees: 71,
            azimuthTrue: 344,
            SNRdB: 32
        });
        packet.satellites[2].should.deepEqual({
            prnNumber: 108,        // Galileo PRN (offset by +100)
            elevationDegrees: 41,
            azimuthTrue: 147,
            SNRdB: 33
        });
        packet.satellites[3].should.deepEqual({
            prnNumber: 111,        // Galileo PRN (offset by +100)
            elevationDegrees: 25,
            azimuthTrue: 233,
            SNRdB: 34
        });
    });

    it("parses GLONASS satellites correctly", (): void => {
        const sentence = appendChecksumFooter("$GLGSV,2,1,08,73,42,069,43,74,35,124,42,84,81,197,39,85,27,309,41");
        const packet = parseNmeaSentence(sentence) as GSVPacket;

        packet.should.have.property("sentenceId", "GSV");
        packet.should.have.property("talkerId", "GL");
        packet.should.have.property("numberOfMessages", 2);
        packet.should.have.property("messageNumber", 1);
        packet.should.have.property("satellitesInView", 8);

        packet.satellites.should.be.instanceof(Array).and.have.lengthOf(4);
        packet.satellites[0].should.deepEqual({
            prnNumber: 73,         // GLONASS PRN (no offset)
            elevationDegrees: 42,
            azimuthTrue: 69,
            SNRdB: 43
        });
        packet.satellites[1].should.deepEqual({
            prnNumber: 74,         // GLONASS PRN (no offset)
            elevationDegrees: 35,
            azimuthTrue: 124,
            SNRdB: 42
        });
        packet.satellites[2].should.deepEqual({
            prnNumber: 84,
            elevationDegrees: 81,
            azimuthTrue: 197,
            SNRdB: 39
        });
        packet.satellites[3].should.deepEqual({
            prnNumber: 85,
            elevationDegrees: 27,
            azimuthTrue: 309,
            SNRdB: 41
        });
    });

    it("parses BeiDou satellites correctly", (): void => {
        const sentence = appendChecksumFooter("$GBGSV,2,1,05,03,42,069,43,04,35,124,42,07,81,197,39,09,27,309,41");
        const packet = parseNmeaSentence(sentence) as GSVPacket;

        packet.should.have.property("sentenceId", "GSV");
        packet.should.have.property("talkerId", "GB");
        packet.should.have.property("numberOfMessages", 2);
        packet.should.have.property("messageNumber", 1);
        packet.should.have.property("satellitesInView", 5);

        packet.satellites.should.be.instanceof(Array).and.have.lengthOf(4);
        packet.satellites[0].should.deepEqual({
            prnNumber: 203,        // BeiDou PRN (offset by +200)
            elevationDegrees: 42,
            azimuthTrue: 69,
            SNRdB: 43
        });
        packet.satellites[1].should.deepEqual({
            prnNumber: 204,        // BeiDou PRN (offset by +200)
            elevationDegrees: 35,
            azimuthTrue: 124,
            SNRdB: 42
        });
        packet.satellites[2].should.deepEqual({
            prnNumber: 207,
            elevationDegrees: 81,
            azimuthTrue: 197,
            SNRdB: 39
        });
        packet.satellites[3].should.deepEqual({
            prnNumber: 209,
            elevationDegrees: 27,
            azimuthTrue: 309,
            SNRdB: 41
        });
    });

    // Added test for secondary GLONASS
    it("handles secondary GLONASS correctly", (): void => {
        const sentence = appendChecksumFooter("$GLGSV,1,1,04,88,45,123,41,89,67,321,42,,,,,,,,,6");
        const packet = parseNmeaSentence(sentence) as GSVPacket;

        packet.satellites.should.be.instanceof(Array).and.have.lengthOf(2);
        packet.satellites[0].should.deepEqual({
            prnNumber: 88,         // Secondary GLONASS PRN (no offset)
            elevationDegrees: 45,
            azimuthTrue: 123,
            SNRdB: 41
        });
        packet.satellites[1].should.deepEqual({
            prnNumber: 89,
            elevationDegrees: 67,
            azimuthTrue: 321,
            SNRdB: 42
        });
    });
});

