from io import StringIO
import unittest
import sys
sys.path.append(".")
from reademptionlib.gff3 import Gff3Parser, Gff3Entry

class TestGff3Parser(unittest.TestCase):

    def setUp(self):
        self.gff3parser = Gff3Parser()
        self.example_data = ExampleData()

    def test_entries(self):
        gff_fh = StringIO(self.example_data.gff_content_1)
        entry_seq_ids = [entry.seq_id for entry 
                        in self.gff3parser.entries(gff_fh)]
        self.assertListEqual(
            ['foo01', 'foo01', 'foo02', 'foo02'], entry_seq_ids)
        
class TestGff3Entry(unittest.TestCase):

    def test_entry_creation_1(self):
        gff3entry = Gff3Entry({
                "seq_id" : "IDfoobar2342",
                "source" : "a_prog",
                "feature" : "gene",
                "start" : "1984",
                "end" : "2001",
                "score" : "1323",
                "strand" : "+",
                "phase" : ".",
                "attributes" : "ID=foo00001;Name=foo"})
        self.assertEqual(gff3entry.seq_id, "IDfoobar2342")
        self.assertEqual(gff3entry.source, "a_prog")
        self.assertEqual(gff3entry.feature, "gene")
        self.assertEqual(gff3entry.start, 1984)
        self.assertEqual(gff3entry.end, 2001)
        self.assertEqual(gff3entry.score, "1323")
        self.assertEqual(gff3entry.strand, "+")
        self.assertEqual(gff3entry.phase, ".")
        self.assertDictEqual(
            gff3entry.attributes, {"ID": "foo00001", "Name": "foo"})

    def test_entry_creation_1(self):
        gff3entry = Gff3Entry({
                "seq_id" : "IDfoobar2342",
                "source" : "a_prog",
                "feature" : "gene",
                "start" : "1984",
                "end" : "2001",
                "score" : "1323",
                "strand" : "+",
                "phase" : ".",
                "attributes" : "ID=foo00001;Name=foo"})
        self.assertEqual(gff3entry.seq_id, "IDfoobar2342")
        self.assertEqual(gff3entry.source, "a_prog")
        self.assertEqual(gff3entry.feature, "gene")
        self.assertEqual(gff3entry.start, 1984)
        self.assertEqual(gff3entry.end, 2001)
        self.assertEqual(gff3entry.score, "1323")
        self.assertEqual(gff3entry.strand, "+")
        self.assertEqual(gff3entry.phase, ".")
        self.assertDictEqual(
            gff3entry.attributes, {"ID": "foo00001", "Name": "foo"})
        self.assertEqual(gff3entry.attribute_string, "ID=foo00001;Name=foo")

    def test_entry_creation_2(self):
        gff3entry = Gff3Entry({
                "seq_id" : "accession_424",
                "source" : "make",
                "feature" : "CDS",
                "start" : "101",
                "end" : "199",
                "score" : "0.888",
                "strand" : "-",
                "phase" : "1",
                "attributes" : "ID=blub1;Name=wow01"})
        self.assertEqual(gff3entry.seq_id, "accession_424")
        self.assertEqual(gff3entry.source, "make")
        self.assertEqual(gff3entry.feature, "CDS")
        self.assertEqual(gff3entry.start, 101)
        self.assertEqual(gff3entry.end, 199)
        self.assertEqual(gff3entry.score, "0.888")
        self.assertEqual(gff3entry.strand, "-")
        self.assertEqual(gff3entry.phase, "1")
        self.assertDictEqual(
            gff3entry.attributes, {"ID": "blub1", "Name": "wow01"})
        self.assertEqual(gff3entry.attribute_string, "ID=blub1;Name=wow01")

    def test_entry_creation_3(self):
        """Test that start and end are sorted. """
        gff3entry = Gff3Entry({
                "seq_id" : "accession_111",
                "source" : "make",
                "feature" : "CDS",
                "start" : "1000",
                "end" : "1",
                "score" : "",
                "strand" : "-",
                "phase" : "",
                "attributes" : "locus_tag=boing"})
        self.assertEqual(gff3entry.start, 1)
        self.assertEqual(gff3entry.end, 1000)

    def test_string_creation(self):
        gff3entry = Gff3Entry({
                "seq_id" : "accession_111",
                "source" : "make",
                "feature" : "CDS",
                "start" : "1000",
                "end" : "1",
                "score" : "0.5",
                "strand" : "-",
                "phase" : ".",
                "attributes" : "locus_tag=boing;note=zoong"})
        self.assertEqual(
            str(gff3entry), 
            "accession_111\tmake\tCDS\t1\t1000\t0.5\t-\t.\t"
            "locus_tag=boing;note=zoong")

class ExampleData(object):
    
    gff_content_1 ="""##gff-version 3
foo01	ta_prog	gene	100	200	.	+	.	ID=bar01;Name=blub
foo01	a_prog	gene	400	500	.	+	.	ID=bar02;Name=limbo
foo02	a_prog	gene	400	500	.	+	.	ID=bar03
foo02	a_prog	CDS	400	500	.	+	.	ID=bar03;Name=bla
"""

if __name__ == "__main__":
	unittest.main()


