#!/usr/bin/env python2.7
import sys
import os
import difflib
import unittest
from ucscGb.gbData.ra.raFile import RaFile
from ucscGb.gbData.ra.raStanza import RaStanza

def DiffExpected(outStr, expFileName, outFileName):
    file = open(os.getcwd() + '/input/' +  expFileName)
    outfile = open(os.getcwd() + '/output/' + outFileName, 'w')
    expected = file.read()

    outfile.write('========Expected========\n')
    outfile.write(expected)
    outfile.write('=========Output=========\n')
    outfile.write(outStr)
    outfile.write('========================\n')

    diffstr = ''
    for line in difflib.unified_diff(expected, outStr, 'expected', 'out'):
        diffstr += line
        outfile.write(line)

    outfile.close()
    return (len(diffstr) > 0)


class DiffCheck(unittest.TestCase):

    def testBasicDiff(self):                          
        """diffs basic input for core rafile functionality"""
        rafile = RaFile(os.getcwd() + '/input/BasicDiff.ra')
        self.failIf(DiffExpected(rafile.__str__(), 'BasicDiff.ra', 'BasicDiff.out'))


    def testCommentsDiff(self):
        """diff to ensure that comments are preserved"""
        rafile = RaFile(os.getcwd() + '/input/CommentsDiff.ra')
        self.failIf(DiffExpected(rafile.__str__(), 'CommentsDiff.ra', 'CommentsDiff.out'))
        

#    def testInlineCommentsDiff(self):
#        """diff to ensure that inline comments are preserved"""
#        rafile = RaFile()
#        rafile.read(os.getcwd() + '/input/InlineCommentsDiff.ra')
#        self.failIf(DiffExpected(rafile.__str__(),
#            'InlineCommentsDiff.ra',
#            'InlineCommentsDiff.out'))
        

class InvalidFilesCheck(unittest.TestCase):

    def testDuplicateKeys(self):
        """makes sure that duplicate keys are caught"""
        rafile = RaFile()
        self.assertRaises(KeyError, rafile.read, os.getcwd() + '/input/DuplicateKeys.ra')


    def testMisplacedKeys(self):
        """checks if keys in the incorrect place are caught"""
        rafile = RaFile()
        self.assertRaises(KeyError, rafile.read, os.getcwd() + '/input/MisplacedKeys.ra')


    def testNonExistentFile(self):
        """checks if invalid files are caught"""
        rafile = RaFile()
        self.assertRaises(IOError, rafile.read, os.getcwd() + '/input/FileDoesNotExist.ra')


#    def testNonNewlineFile(self):
#        """ensures file ends in newline"""
#        rafile = RaFile()
#        self.assertRaises(IOError, rafile.read, os.getcwd() + '/input/NonNewlineFile.ra')


#    def testInvalidComments(self):
#        """ensures file doesn't have comments in the middle of stanzas"""
#        rafile = RaFile()
#        self.assertRaises(KeyError, rafile.read, os.getcwd() + '/input/InvalidComments.ra')


class FunctionalityCheck(unittest.TestCase):
 
    def testIterKeys(self):
        """tests that iterkeys works"""
        rafile = RaFile(os.getcwd() + '/input/FunctionalityCheck.ra')
       
        outstr = ''
        for entry in rafile.iterkeys():
            outstr += str(entry) + '\n'

        self.failIf(DiffExpected(outstr,
            'IterKeys.ra',
            'IterKeys.out'))
       

    def testIterValues(self):
        """tests that itervalues works"""
        rafile = RaFile(os.getcwd() + '/input/FunctionalityCheck.ra')

        outstr = ''
        for entry in rafile.itervalues():
            outstr += str(entry) + '\n'

        self.failIf(DiffExpected(outstr,
            'IterValues.ra',
            'IterValues.out'))


    def testIterItems(self):
        """tests that iteritems works"""
        rafile = RaFile(os.getcwd() + '/input/FunctionalityCheck.ra')

        outstr = ''
        for entry in rafile.iteritems():
            outstr += str(entry) + '\n'

        self.failIf(DiffExpected(outstr,
            'IterItems.ra',
            'IterItems.out'))


    def testIterEntryKeys(self):
        """tests that iterkeys works"""
        rafile = RaFile(os.getcwd() + '/input/FunctionalityCheck.ra')

        outstr = ''
        for entry in rafile.itervalues():
            for item in entry.iterkeys():
                outstr += str(item) + '\n'

        self.failIf(DiffExpected(outstr,
            'IterEntryKeys.ra',
            'IterEntryKeys.out'))


    def testIterEntryValues(self):
        """tests that iterkeys works"""
        rafile = RaFile(os.getcwd() + '/input/FunctionalityCheck.ra')

        outstr = ''
        for entry in rafile.itervalues():
            for item in entry.itervalues():
                outstr += str(item) + '\n'

        self.failIf(DiffExpected(outstr,
            'IterEntryValues.ra',
            'IterEntryValues.out'))


    def testIterEntryItems(self):
        """tests that iterkeys works"""
        rafile = RaFile(os.getcwd() + '/input/FunctionalityCheck.ra')

        outstr = ''
        for entry in rafile.itervalues():
            for item in entry.iteritems():
                outstr += str(item) + '\n'

        self.failIf(DiffExpected(outstr, 'IterEntryItems.ra', 'IterEntryItems.out'))


    def testGetItem(self):
        """tests that getting stanzas works"""
        rafile = RaFile(os.getcwd() + '/input/FunctionalityCheck.ra')

        outstr = ''
        outstr += str(rafile['valA']) + '\n'

        self.failIf(DiffExpected(outstr, 'GetItem.ra', 'GetItem.out'))


    def testDeleteItem(self):
        """tests that removing items works"""
        rafile = RaFile(os.getcwd() + '/input/FunctionalityCheck.ra')

        outstr = ''
        del rafile['valA']
        outstr = str(rafile)

        self.failIf(DiffExpected(outstr, 'DeleteItem.ra', 'DeleteItem.out'))


if __name__ == '__main__':
    if not os.path.isdir(os.getcwd() + '/output'):
        os.mkdir(os.getcwd() + '/output')
    unittest.main()
