import os
import unittest
import struct
from SMART.Java.Python.ncList.NCList import NCList
from SMART.Java.Python.misc import Utils
from commons.core.utils.FileUtils import FileUtils
from SMART.Java.Python.ncList.test.MockFindOverlapsWithSeveralIntervals import *
from commons.core.parsing.GffParser import GffParser
from SMART.Java.Python.ncList.FileSorter import FileSorter

class Test_F_NCList(unittest.TestCase):

    def setUp(self):
        self._inputGff3FileName = 'sortedFile.gff3'
        self._sortedFileName    = 'sortedFile.pkl'
        self._expHFileName      = 'expH.bin'
        self._expLFileName      = 'expL.bin'
        self._obsHFileName      = 'H.bin'
        self._obsLFileName      = 'L.bin'
        self._addressFileName   = 'address.txt'
        self._writeGFF3File(self._inputGff3FileName)
        self._ncList = NCList(0)
        self._ncList.setChromosome("chr1")
        
    def tearDown(self):
        return
        for fileName in (self._inputGff3FileName, self._sortedFileName, self._expHFileName, self._expLFileName, self._obsHFileName, self._obsLFileName, self._addressFileName):
            if os.path.exists(fileName):
                os.remove(fileName)
        
    def _sortAndBuild(self):
        parser = GffParser(self._inputGff3FileName)
        fs = FileSorter(parser, 0)
        fs.setOutputFileName(self._sortedFileName)
        fs.sort()
        self._ncList.setFileName(self._sortedFileName)
        self._ncList.setNbElements(parser.getNbTranscripts())
        self._ncList.buildLists()

    def test_run_with_one_elementSubList(self):
        iMock = MockFindOverlapsWithOneInterval()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFile_one_elementSubList()
        self._writeExpLFile_one_elementSubList()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    
        
    def test_case1(self):
        iMock = MockFindOverlapsWithServeralIntervals_case1()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase1()
        self._writeExpLFileCase1()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    
        
    def test_case2(self):
        iMock = MockFindOverlapsWithServeralIntervals_case2()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase2()
        self._writeExpLFileCase2()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    
        
    def test_case3(self):
        iMock = MockFindOverlapsWithServeralIntervals_case3()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase3()
        self._writeExpLFileCase3()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    
    
    def test_case4_5(self):
        iMock = MockFindOverlapsWithServeralIntervals_case4_5()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase4_5()
        self._writeExpLFileCase4_5()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    

    def test_case6_7(self):
        iMock = MockFindOverlapsWithServeralIntervals_case6_7()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase6_7()
        self._writeExpLFileCase6_7()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    

    def test_case8(self):
        iMock = MockFindOverlapsWithServeralIntervals_case8()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase8()
        self._writeExpLFileCase8()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    
        
    def test_case9(self):
        iMock = MockFindOverlapsWithServeralIntervals_case9()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase9()
        self._writeExpLFileCase9()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    
 
    def test_case10(self):
        iMock = MockFindOverlapsWithServeralIntervals_case10()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase10()
        self._writeExpLFileCase10()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    
 
    def test_case11(self):
        iMock = MockFindOverlapsWithServeralIntervals_case11()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase11()
        self._writeExpLFileCase11()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    
               
    def test_case12(self):
        iMock = MockFindOverlapsWithServeralIntervals_case12()
        iMock.write(self._inputGff3FileName)
        self._sortAndBuild()
        self._writeExpHFileCase12()
        self._writeExpLFileCase12()
        self.assertTrue(FileUtils.are2FilesIdentical(self._expHFileName, self._ncList._hFileName))
        self.assertTrue(FileUtils.are2FilesIdentical(self._expLFileName, self._ncList._lFileName))    

    def _writeGFF3File(self, fileName):
        f = open(fileName, "w")
        f.write("chr1\ttest\ttest2.1\t9\t1000\t1001\t+\t.\tID=test2.1;Name=test2.1\n")
        f.write("chr1\ttest\ttest2.2\t50\t350\t301\t+\t.\tID=test2.2;Name=test2.2\n")
        f.write("chr1\ttest\ttest2.3\t100\t600\t501\t+\t.\tID=test2.3;Name=test2.3\n")
        f.write("chr1\ttest\ttest2.4\t200\t450\t251\t+\t.\tID=test2.4;Name=test2.4\n")
        f.write("chr1\ttest\ttest2.5\t700\t950\t251\t+\t.\tID=test2.5;Name=test2.5\n")
        f.write("chr1\ttest\ttest2.6\t800\t900\t101\t+\t.\tID=test2.6;Name=test2.6\n")
        f.write("chr1\ttest\ttest2.7\t1200\t1300\t101\t+\t.\tID=test2.7;Name=test2.7\n")
        f.close()
    
    def _writeBinFile(self, fileName, elements):
        handle = open(fileName, "wb")
        for element in elements:
            handle.write(struct.pack('l', element))
        handle.close()
                     
    def _writeExpHFile(self, HFileName):
        list = [0, 2, 48, 3, -1, -1, -1, -1, 120, 1, 144, 1, -1, -1, -1, -1]
        H = open(HFileName, 'wb')
        
        for item in list:
            item = struct.pack('l', item)
            H.write(item)
        H.close()
        
    def _writeExpHFile_with_empty_SubParentDict(self, HFileName):
        list = [0, 1, -1, -1]
        H = open(HFileName, 'wb')
        
        for item in list:
            item = struct.pack('l', item)
            H.write(item)
        H.close()
        
    def _writeExpHFile_one_elementSubList(self):
        elements = [0, 1]
        self._writeBinFile(self._expHFileName, elements)
     
    def _writeExpHFileCase1(self):
        elements = [0, 2, 2, 3, 5, 1, 6, 1]
        self._writeBinFile(self._expHFileName, elements)
                     
    def _writeExpHFileCase2(self):
        elements = [0, 2, 2, 1, 3, 1, 4, 1]
        self._writeBinFile(self._expHFileName, elements)
                     
    def _writeExpHFileCase3(self):
        elements = [0, 2, 2, 1, 3, 1, 4, 2]
        self._writeBinFile(self._expHFileName, elements)
                     
    def _writeExpHFileCase4_5(self):
        elements = [0, 1, 1, 1, 2, 1]
        self._writeBinFile(self._expHFileName, elements)
                                              
    def _writeExpHFileCase6_7(self):
        elements = [0, 1, 1, 4]
        self._writeBinFile(self._expHFileName, elements)
              
    def _writeExpHFileCase8(self):
        elements = [0, 1, 1, 2]
        self._writeBinFile(self._expHFileName, elements)
              
    def _writeExpHFileCase9(self):
        elements = [0, 2, 2, 1]
        self._writeBinFile(self._expHFileName, elements)
              
    def _writeExpHFileCase10(self):
        elements = [0, 3, 3, 3]
        self._writeBinFile(self._expHFileName, elements)
              
    def _writeExpHFileCase11(self):
        elements = [0, 2, 2, 2, 4, 2]
        self._writeBinFile(self._expHFileName, elements)
        
    def _writeExpHFileCase12(self):
        elements = [0, 1, 1, 3, 4, 1]
        self._writeBinFile(self._expHFileName, elements)
        
    def _writeExpLFile_one_elementSubList(self):
        elements = [0, 1000, 0, -1, -1]
        self._writeBinFile(self._expLFileName, elements)

    def _writeExpLFileCase1(self):
        elements = [   0, 1000,    0,  1, -1, \
                    1200, 1300, 2345, -1, -1, \
                      50,  350,  391, -1,  0, \
                     100,  600,  781,  2,  0, \
                     700,  950, 1563,  3,  0, \
                     200,  450, 1172, -1,  3, \
                     800,  900, 1954, -1,  4]
        self._writeBinFile(self._expLFileName, elements)
        
    def _writeExpLFileCase2(self):
        elements = [   0,  500,    0,  1, -1, \
                     900, 1200, 1561, -1, -1, \
                      50,  450,  389,  2,  0, \
                     100,  400,  779,  3,  2, \
                     100,  200, 1170, -1,  3]
        self._writeBinFile(self._expLFileName, elements)
        
    def _writeExpLFileCase3(self):
        elements = [   0,  500,    0,  1, -1, \
                     800, 1000, 1952, -1, -1, \
                      50,  450,  389,  2,  0, \
                     100,  400,  779,  3,  2, \
                     100,  200, 1170, -1,  3, \
                     300,  400, 1561, -1,  3]
        self._writeBinFile(self._expLFileName, elements)
             
    def _writeExpLFileCase4_5(self):
        elements = [   0, 1000,    0,  1, -1, \
                     200,  800,  391,  2,  0, \
                     400,  600,  782, -1,  1]
        self._writeBinFile(self._expLFileName, elements)
                           
    def _writeExpLFileCase6_7(self):
        elements = [   0, 1000,    0,  1, -1, \
                     100,  300,  391, -1,  0, \
                     400,  500,  782, -1,  0, \
                     510,  520, 1173, -1,  0, \
                     850,  950, 1563, -1,  0]
        self._writeBinFile(self._expLFileName, elements)
        
    def _writeExpLFileCase8(self):
        elements = [   0, 1000,    0,  1, -1, \
                     100,  200,  391, -1,  0, \
                     300,  400,  782, -1,  0]
        self._writeBinFile(self._expLFileName, elements)
        
    def _writeExpLFileCase9(self):
        elements = [   0, 1000,    0,  1, -1, \
                     800, 1200,  782, -1, -1, \
                     600,  700,  391, -1,  0]
        self._writeBinFile(self._expLFileName, elements)
        
    def _writeExpLFileCase10(self):
        elements = [   0, 1000,    0,  1, -1, \
                    1200, 1300, 1576, -1, -1, \
                    1400, 1500, 1972, -1, -1, \
                     100,  200,  394, -1,  0, \
                     300,  400,  788, -1,  0, \
                     500,  600, 1182, -1,  0]
        self._writeBinFile(self._expLFileName, elements)
        
    def _writeExpLFileCase11(self):
        elements = [   0,  500,    0,  1, -1, \
                     700,  900, 1180,  2, -1, \
                     100,  200,  392, -1,  0, \
                     300,  400,  786, -1,  0, \
                     710,  720, 1574, -1,  1, \
                     740,  750, 1967, -1,  1]
        self._writeBinFile(self._expLFileName, elements)
              
    def _writeExpLFileCase12(self):
        elements = [   0, 1400,    0,  1, -1, \
                     300,  500,  368,  2,  0, \
                     800, 1100, 1106, -1,  0, \
                    1200, 1300, 1476, -1,  0, \
                     300,  500,  737, -1,  1]
        self._writeBinFile(self._expLFileName, elements)
              
if __name__ == "__main__":
    unittest.main()
