
from CCP4PluginScript import CPluginScript
import os


class ProvideSequence(CPluginScript):

    TASKNAME = 'ProvideSequence'                                  # Task name - should be same as class name
    TASKCOMMAND = ''                                     # The command to run the executable
    TASKVERSION= 0.0                                     # Version of this plugin
    COMTEMPLATE = None                                   # The program com file template
    COMTEMPLATEFILE = None                               # Name of file containing com file template
    RUNEXTERNALPROCESS=False

    '''
    def __init__(self,parent=None,name=None,workDirectory=''):
      CPluginScript. __init__(self,parent=parent,name=name)
    '''
    
    def startProcess(self, command, **kw):
        import tempfile
        from ProvideAlignment import importAlignment
        from lxml import etree
        
        root = etree.Element('ProvideSequence')
        
        # Create a temporary file to store the sequence(s) that will be used
        tempFile = tempfile.NamedTemporaryFile(suffix='.txt',delete=False)
        tempFile.file.write(self.container.controlParameters.SEQUENCETEXT.__str__())
        tempFile.close()
        
        #Attempt to interpret that as an alignment and/or stack of sequences
        alignment, format, commentary = importAlignment(tempFile.name)
        
        commentaryNode = etree.SubElement(root,"Commentary")
        commentaryNode.text = commentary.getvalue()
        
        if alignment is None:
            with open(self.makeFileName('PROGRAMXML'),'w') as programXML:
                programXML.write (etree.tostring(root,pretty_print=True))
            self.reportStatus(CPluginScript.UNSATISFACTORY)
            return
        
        formatNode = etree.SubElement(root,'Format')
        formatNode.text = format
        
        from Bio import SeqIO
        for iSeq, seq in enumerate(alignment):
            outputList = self.container.outputData.SEQUENCEFILE_LIST
            outputList.append(outputList.makeItem())
            outputFile = outputList[-1]
            outputFile.setFullPath(os.path.normpath(os.path.join(self.getWorkDirectory(),'SEQUENCE'+str(iSeq)+'.fasta')))
            import StringIO
            outputString = StringIO.StringIO()
            with open(outputFile.__str__(),'w') as outputFileHandle:
                SeqIO.write([seq],outputFileHandle,'fasta')
            outputFile.annotation = seq.id + '-' + seq.description
        
            sequenceElement = etree.SubElement(root,'Sequence')
            outputString = StringIO.StringIO()
            SeqIO.write([seq],outputString,'fasta')
            sequenceElement.text = outputString.getvalue()
            for property in ['id','name','description','seq']:
                newElement = etree.SubElement(sequenceElement,property)
                newElement.text = str(getattr(seq,property,'Undefined'))

        with open(self.makeFileName('PROGRAMXML'),'w') as programXML:
            programXML.write(etree.tostring(root,pretty_print=True))
        return CPluginScript.SUCCEEDED


#====================================================================================================
# PLUGIN TESTS
# See Python documentation on unittest module

import unittest

class testProvideSequence(unittest.TestCase):

   def setUp(self):
    # make all background jobs wait for completion
    # this is essential for unittest to work
    from CCP4Modules import QTAPPLICATION,PROCESSMANAGER
    self.app = QTAPPLICATION()
    PROCESSMANAGER().setWaitForFinished(10000)

   def tearDown(self):
    from CCP4Modules import PROCESSMANAGER
    PROCESSMANAGER().setWaitForFinished(-1)

   def test_1(self):
     from CCP4Modules import QTAPPLICATION
     wrapper = ProvideSequence(parent=QTAPPLICATION(),name='ProvideSequence_test1')
     wrapper.container.loadDataFromXml()
     

def TESTSUITE():
  suite = unittest.TestLoader().loadTestsFromTestCase(testProvideSequence)
  return suite

def testModule():
  suite = TESTSUITE()
  unittest.TextTestRunner(verbosity=2).run(suite)
