package htsjdk.samtools.cram.encoding;

import htsjdk.HtsjdkTest;
import htsjdk.samtools.cram.encoding.core.BetaIntegerEncoding;
import htsjdk.samtools.cram.encoding.external.ExternalByteArrayEncoding;
import htsjdk.samtools.cram.encoding.external.ExternalIntegerEncoding;
import htsjdk.samtools.cram.structure.EncodingID;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class ByteArrayLenEncodingTest extends HtsjdkTest {

    @DataProvider(name = "tests")
    public Object[][] testData() {
        return new Object[][] {

                // 1. BetaIntegerEncoding ID
                // 2. length of the BetaIntegerEncoding params, encoded via ITF8
                // 3. BetaIntegerEncoding params, encoded via ITF8
                // 4. ExternalByteArrayEncoding ID
                // 5. length of the ExternalByteArrayEncoding params, encoded via ITF8
                // 6. ExternalByteArrayEncoding params, encoded via ITF8

                // see also: BetaIntegerEncodingTest and ExternalByteArrayEncodingTest

                {0, 8, 127, new byte[] {
                        (byte) EncodingID.BETA.getId(),
                        2,
                        0, 8,
                        (byte) EncodingID.EXTERNAL.getId(),
                        1,
                        127 }},

                {127, 32, 0, new byte[] {
                        (byte) EncodingID.BETA.getId(),
                        2,
                        127, 32,
                        (byte) EncodingID.EXTERNAL.getId(),
                        1,
                        0 }},

                {128, 32, -1, new byte[] {
                        (byte) EncodingID.BETA.getId(),
                        3,
                        // 128 in ITF8
                        (byte) 0x80, (byte) 0x80,
                        32,
                        (byte) EncodingID.EXTERNAL.getId(),
                        5,
                        // -1 in ITF8
                        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF }},
        };
    }

    @Test(dataProvider = "tests")
    public void paramsTest(final int offset, final int bitsPerValue, final int externalBlockContentId, final byte[] expected) {
        // arbitrary choice here: any Integer, byte[] encoding pair will do

        final CRAMEncoding<Integer> constructedLength = new BetaIntegerEncoding(offset, bitsPerValue);
        final CRAMEncoding<byte[]> constructedValues = new ExternalByteArrayEncoding(externalBlockContentId);
        final ByteArrayLenEncoding constructed = new ByteArrayLenEncoding(constructedLength, constructedValues);
        Assert.assertEquals(constructed.toSerializedEncodingParams(), expected);

        final ByteArrayLenEncoding params = ByteArrayLenEncoding.fromSerializedEncodingParams(expected);
        Assert.assertEquals(params.toSerializedEncodingParams(), expected);
    }

    @Test
    public void testToString() {
        final ByteArrayLenEncoding encoding = new ByteArrayLenEncoding(
                new ExternalIntegerEncoding(27),
                new ExternalByteArrayEncoding(29));
        Assert.assertTrue(encoding.toString().contains("27"));
        Assert.assertTrue(encoding.toString().contains("29"));
    }
}
