#!/usr/bin/python
#coding=utf-8
#@+leo-ver=5-thin
#@+node:bob.20180205135005.1: * @file leo_babel/tests/lib_test.py
#@@first
#@@first
#@@language python
#@@tabwidth -4

#@+<< imports >>
#@+node:bob.20180205135704.1: ** << imports >>
import datetime
# import time

import leo.core.leoGlobals as leoG
#@-<< imports >>
#@+<< version >>
#@+node:bob.20180205135712.1: ** << version >>
version = '1.0'
#@-<< version >>

#@+others
#@+node:bob.20180115163141.1: ** findTests()
def findTests(cmdrT):
    """ Find all the Leo-Babel test nodes in the specified file

    Arguments:
        cmdrT: Leo-Editor commander for the file containing tests

    Returns:
        pos: Position of the next Leo-Babel test node

    Raises:
        StopIteration:  No more Leo-Babel test nodes
    """

    rootParentList = cmdrT.find_h(r'.*\|Tests\|$')
    for rpx in rootParentList:
        for lbr in rpx.children_iter():
            yield lbr
#@+node:bob.20180116151937.1: ** class EsCapture
class EsCapture(object):
    """ Object to capture leoG.es() output
    """

    #@+others
    #@+node:bob.20180116152036.1: *3* __init__()
    def __init__(self):
        self._es = leoG.es
        leoG.es = self.esCapture
        self._colorDict = None
    #@+node:bob.20180116152548.1: *3* beginCollection()
    def beginCollection(self):
        """ Begin collection of leoG.es() output

        Arguments:
            None

        Returns:
            None
        """

        #leoG.trace('Begin Collection')
        self._colorDict = dict()
    #@+node:bob.20180116152729.1: *3* endCollection()
    def endCollection(self):
        """ End collection of leoG.es() output

        Arguments:
            None

        Returns:
            None
        """

        self._collectedDict = self._colorDict
        self._colorDict = None
        #leoG.trace('End Collection')
    #@+node:bob.20180116151252.1: *3* esCapture()
    def esCapture(self, *args, **keys):
        """ Capture the leoG.es() output and then pass it on
        to leoG.es()

        Arguments:
            color:  Color of output
            tabName:  Name of the tab to which to print.

            leoG.es() has other keyword arguments which
            esCapture() ignores.

        Returns:
            None
        """

        #leoG.trace('Entry - args="{0}" keys={1}'.format(args, keys))
        color = keys.get('color', 'black')
        assert not color is None
        if self._colorDict is not None:
            #leoG.trace('Save')
            listx = self._colorDict.get(color, list())
            listx.append((args, keys))
            self._colorDict[color] = listx
        self._es(*args, **keys)
    #@+node:bob.20180116153437.1: *3* getData()
    def getData(self):
        """ Return the collected data

        Arguments:
            self:  EsCapture instance

        Returns:
            colorDict:  Dictionary
                key:  Color or output
                value: List of lists of args to leoG.es()
        """

        return self._collectedDict
    #@-others
#@+node:bob.20180116154559.1: ** class TestCmdr
class TestCmdr(object):
    """ Global Parameters for Test Code
    """

    #@+others
    #@+node:bob.20180116154657.1: *3* __init__()
    def __init__(self, cmdrT, fdR):
        """ Initialize Test Globals
        
        Arguments:
            cmdrT:  Commander for Leo-Editor file containing the tests
            fdR:    File descriptor for results files
        
        Returns:
            None
        """

        #@+others
        #@+node:bob.20180116154845.1: *4* _getColor()
        def _getColor(cmdr, settingName, default=None):
            """ Add a default option to c.config.getColor()
            """

            colorx = cmdr.config.getColor(settingName)
            if colorx:
                return colorx
            else:
                return default
        #@+node:bob.20180116154857.1: *4* _getString()
        def _getString(cmdr, settingName, default=None):
            """ Add a default option to c.config.getString()
            """

            strx = cmdr.config.getString(settingName)
            if strx:
                return strx
            else:
                return default
        #@-others

        self.colorStdout = _getColor(cmdrT, 'Leo-Babel-stdout', default='#00ff00')
        self.colorStderr = _getColor(cmdrT, 'Leo-Babel-stderr', default='#A020F0')
        self.colorCompletion = _getColor(cmdrT, 'Leo-Babel-completion', default='#FFD700')
        self.nodeCreationDefault = cmdrT.config.getBool('Leo-Babel-Node-Creation-Default', default=True)
        self.interpreterPython = _getString(cmdrT, 'Leo-Babel-Python', default='python3')
        self.interpreterShell = _getString(cmdrT, 'Leo-Babel-Shell', default='bash')

        self.esCapture = EsCapture()

        self.testCnt = 0
        self.babelExecCnt = 0

        fdR.write('||* Tests *|| {0}\n'.format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%s')))
    #@-others
#@+node:bob.20180125160225.14: ** runTests()
def  runTests(itPoll, cmdrT, fdR, testCmdr, genFindTests):
    """ Run the tests polling at idle time

    Arguments:
        itPoll: Idle Time object for runTests()
        cmdrT:  Leo-Editor commander for file containing tests
        fdR:  File descriptor for the results file
        testCmdr:  Test parameters for the file cmdrT
        genFindTests:  Generator returning tests

    Returns:
        None
    """

    #@+others
    #@+node:bob.20180317172851.1: *3* formatCaptured()
    def formatCaptured(capturedList):
        """ Format the captured List for a node body

        Arguments:
            capturedList: List of captured data

        Returns:
            None
        """

        outList = list()
        for linesColor in capturedList:
            lineList = linesColor[0]
            for linex in lineList:
                outList.append(linex.rstrip())
        return '\n'.join(outList) + '\n'
    #@-others

    babelCmdr = cmdrT.user_dict.get('leo_babel')
    if babelCmdr is None:
        testCmdr.babelExecCnt = 0
    else:
        if testCmdr.babelExecCnt >= babelCmdr.babelExecCnt:
            return      # Waiting for test to complete
        else:
            # Most Recent Test has finished.
            testCmdr.babelExecCnt = babelCmdr.babelExecCnt
            fdR.write('||* Test Name *|| {0}\n'.format(testCmdr.testRootMostRecnt.h))
            testCmdr.esCapture.endCollection()
            data = testCmdr.esCapture.getData()
            colorList = list(data.keys())
            colorList.sort()
            for color in colorList:
                outList = data[color]
                if color == testCmdr.colorStdout:
                    fdR.write('||* stdout *||\n')
                    fdR.write(formatCaptured(outList))
                elif color == testCmdr.colorStderr:
                    fdR.write('||* stderr *||\n')
                    fdR.write(formatCaptured(outList))
                elif color == testCmdr.colorCompletion:
                    fdR.write('||* Completion *||\n')
                    fdR.write(formatCaptured(outList))
                else:
                    fdR.write('||* Other Color *|| {0}\n'.format(color))
                    fdR.write(formatCaptured(outList))
    # Most Recent Test (if any) if done and its output recorded
    # Start the next test.
    try:
        testRoot = next(genFindTests)
    except StopIteration:
        itPoll.stop()
        fdR.close()
        return
    testCmdr.testRootMostRecnt = testRoot
    cmdrT.selectPosition(testRoot)  # babel_exec() expects the root node to be selected.
    testCmdr.esCapture.beginCollection()
    cmdrT.executeMinibufferCommand('babel-exec-p')
    # cmdrT.executeMinibufferCommand() returns immediately--Long before the command is executed.
#@+node:bob.20180205135258.1: ** main()
def main():
    """ Command Line Program Entry point
    """

    raise NotImplementedError('{0} is not a command line program.'.format(__file__))
#@-others

if __name__ == "__main__":
    main()
#@-leo
