package net.sf.picard.illumina.parser.readers;

import net.sf.picard.PicardException;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.io.File;

public class PosFileReaderTest {
    //need to test for negatives
    public static final File TestDir = new File("testdata/net/sf/picard/illumina/readerTests");
    public static final File InvalidNamePosFile = new File(TestDir, "pos_failing1_pos.txt");

    public static final File PassingPosFile = new File(TestDir, "s_2_1101_pos.txt");
    public static final int PassingTile = 1101;
    public static final int PassingLane = 2;
    public static final float [][] PassingPosFloatCoord = {
        {17.80f, 0.30f},  {23.70f, 1.70f},  {18.50f, 3.90f},  {22.80f, 4.00f},  {15.90f, 4.20f},
        {19.10f, 5.60f},  {23.90f, 6.70f},  {16.70f, 7.00f},  {21.50f, 7.10f},  {18.90f, 9.30f},
        {17.10f, 10.30f}, {19.90f, 10.80f}, {15.90f, 11.90f}, {21.60f, 12.00f}, {24.80f, 12.40f},
        {17.90f, 14.20f}, {22.00f, 14.50f}, {23.60f, 15.20f}, {20.00f, 15.50f}, {16.30f, 17.30f}
    };
    public static final int [][] PassingPosQSeqCoord = {
        {1178, 1003}, {1237, 1017}, {1185, 1039}, {1228, 1040}, {1159, 1042},
        {1191, 1056}, {1239, 1067}, {1167, 1070}, {1215, 1071}, {1189, 1093},
        {1171, 1103}, {1199, 1108}, {1159, 1119}, {1216, 1120}, {1248, 1124},
        {1179, 1142}, {1220, 1145}, {1236, 1152}, {1200, 1155}, {1163, 1173}
    };

    @Test
    public void validPosFileTest() {
        final PosFileReader pfr = new PosFileReader(PassingPosFile);
        for(int i = 0; i < PassingPosFloatCoord.length; i++) {
            Assert.assertTrue(pfr.hasNext());
            final AbstractIlluminaPositionFileReader.PositionInfo pi = pfr.next();
            comparePositionInfo(pi, i);
        }
        Assert.assertFalse(pfr.hasNext());
        pfr.close();
    }

    public static void comparePositionInfo(final AbstractIlluminaPositionFileReader.PositionInfo pi, final int index) {
        comparePositionInfo(pi, PassingPosFloatCoord[index][0],  PassingPosFloatCoord[index][1],
                                PassingPosQSeqCoord[index][0], PassingPosQSeqCoord[index][1],
                                PassingLane, PassingTile, index);
    }

    public static void comparePositionInfo(final AbstractIlluminaPositionFileReader.PositionInfo pi, final float xPos, final float yPos,
                               final int xQSeqCoord, final int yQSeqCoord, final int lane, final int tile, final int index) {
        Assert.assertEquals(pi.xPos, xPos, "Differs at index: " + index);
        Assert.assertEquals(pi.yPos, yPos, "Differs at index: " + index);
        Assert.assertEquals(pi.xQseqCoord, xQSeqCoord, "Differs at index: " + index);
        Assert.assertEquals(pi.yQseqCoord, yQSeqCoord, "Differs at index: " + index);
        Assert.assertEquals(pi.lane, lane, "Differs at index: " + index);
        Assert.assertEquals(pi.tile, tile, "Differs at index: " + index);
    }

    @Test(expectedExceptions = PicardException.class)
    public void failingNamePosFileTest() {
        final PosFileReader pfr = new PosFileReader(InvalidNamePosFile);
    }

    @DataProvider(name = "invalidDataFiles")
    public Object [][] invalidDataFiles() {
        return new Object[][]{
            {new File(TestDir, "s_1_1101_pos.txt")},
            {new File(TestDir, "s_1_1102_pos.txt")},
            {new File(TestDir, "s_1_1103_pos.txt")}
        };
    }

    @Test(dataProvider="invalidDataFiles", expectedExceptions = PicardException.class)
    public void failingDataPosFileTest(final File file) {
        final PosFileReader pfr = new PosFileReader(file);
        while(pfr.hasNext()) {
            pfr.next();
        }
        pfr.close();
    }

    @Test
    public void zeroLengthFileTest() {
        final PosFileReader pfr = new PosFileReader(new File(TestDir, "s_1_1104_pos.txt"));
        Assert.assertFalse(pfr.hasNext());
    }
}
