#########################################################################
#
# Date: Oct. 2002  Authors: Daniel Stoffler, Michel Sanner
#
#       stoffler@scripps.edu
#       sanner@scripps.edu
#
# Copyright: Daniel Stoffler, Michel Sanner and TSRI
#
#########################################################################

import sys, string
from mglutil.regression import testplus
ed = None
withThreads = 0 # default is: multi-threading off

# allow for additional user input
if len(sys.argv):
    for myArg in sys.argv[1:]:
        if myArg[:11] == 'withThreads':
            withThreads = int(string.strip(myArg)[-1])


def startEditor():
    global ed
    from Vision.VPE import VisualProgramingEnvironment
    ed = VisualProgramingEnvironment(name='Vision', withShell=0)
    ed.root.update_idletasks()
    ed.configure(withThreads=withThreads)
    

def quitEditor():
    ed.master.after(1000, ed.exit_cb )


def pause(sleepTime=0.4):
    from time import sleep
    ed.master.update()
    sleep(sleepTime)


def test_loadStandardLibrary():
    # test if stdlib can be imported
    from Vision.StandardNodes import stdlib
    ed.addLibrary(stdlib)
    ed.root.update_idletasks()


def test_multiCheckbuttons():
    from NetworkEditor.net import Network
    net = Network('testing Multi Checkbuttons')
    ed.addNetwork(net)
    ed.setNetwork(net)
    from Vision.StandardNodes import Eval
    node1 = Eval()
    ed.currentNetwork.addNode(node1,75,75)
    node1.inputPorts[0].widget.set("['apple','banana','orange','lemon']")
    ###################
    from Vision.StandardNodes import MultiCheckbuttonsNE
    node2 = MultiCheckbuttonsNE()
    ed.currentNetwork.addNode(node2,150,150)
    ###################
    conn1 = ed.currentNetwork.connectNodes(node1, node2, 0, 0)
    ###################
    node2.paramPanel.show()
    ed.root.update_idletasks()
    ###################
    node2.inputPorts[1].widget.tkwidget.checkAll()
    net.run()
    net.waitForCompletion() # give time to finish if running multithreaded
    assert len(node2.outputPorts[0].data) == 4 # apple, banana, orange, lemon
    ###################
    node2.inputPorts[1].widget.tkwidget.uncheckAll()
    net.run()
    net.waitForCompletion() # give time to finish if running multithreaded
    assert len(node2.outputPorts[0].data) == 0 # nothing selected
    ###################
    node2.paramPanel.hide()
    ed.deleteNetwork(ed.networks['testing Multi Checkbuttons'])
    

def test_loadNetwork():
    ed.loadNetwork('forLoop_net.py')
    ed.deleteNetwork(ed.networks['forLoop'])


def test_deleteNetwork():
    ed.loadNetwork('forLoop_net.py')
    try:
        ed.deleteNetwork('forLoop')
        raise RuntimeError ('failed to catch bad argument for deleteNetwork')
    except AttributeError:
        pass
    
    ed.deleteNetwork(ed.networks['forLoop'])


def test_addNewNetwork():
    from NetworkEditor.net import Network
    net = Network('regression test network')
    ed.addNetwork(net)
    ed.setNetwork(net)
    pause()
    ed.deleteNetwork(ed.networks['regression test network'])
    

def test_doubleSaveBug1():
    # when a network was saved twice in a row, the import of libraries
    # was omitted
    ed.loadNetwork('forLoop_net.py')
    ed.saveNetwork('foo_net.py')
    ed.saveNetwork('foo_net.py')
    ed.deleteNetwork(ed.networks['forLoop'])
    ed.loadNetwork('foo_net.py')
    ed.deleteNetwork(ed.networks['foo'])
    pause()


def test_doubleSaveBug2():
    # saving a node with source code changed twice in a row did not work
    # first, let's create a new network
    from NetworkEditor.net import Network
    net = Network('1node')
    ed.addNetwork(net)
    ed.setNetwork(net)

    # now add a node (we use the Pass node from StandardNodes)
    from Vision.StandardNodes import Pass
    node = Pass()
    ed.currentNetwork.addNode(node,150,150)
    # change the source code:
    node.sourceCode = \
    "def doit(self, in1):\n    in1=42\n    self.outputData(out1=in1)\n"
    node._modified['sourceCode'] = 1
    
    # save this node, and delete the network
    ed.saveNetwork('1node_net.py')
    ed.deleteNetwork(ed.networks['1node'])

    # load, save and delete the network again
    ed.loadNetwork('1node_net.py')
    ed.saveNetwork('1node_net.py')
    ed.deleteNetwork(ed.networks['1node'])

    # load it and now do some tests:
    ed.loadNetwork('1node_net.py')
    node = ed.currentNetwork.nodes[0]
    passNode = Pass()
    assert node.name == 'Pass'
    assert node.originalClass == passNode.__class__
    assert node.library is None # THIS will change!!

    # let's see if we can still run the node.. it should output 42
    # for this, we have to make the inputport required=0
    node.inputPorts[0].required = 0
    assert node.outputPorts[0].data is None # not run yet
    node.network.run()
    node.network.waitForCompletion() #this is very important 
    #we have to wait for completion before we can test the value.
    #else this test would fail.
    assert node.outputPorts[0].data == 42


def test_standardNodes():
    # add new network
    from Vision.StandardNodes import stdlib
    ed.addLibrary(stdlib)
    from NetworkEditor.net import Network
    net = Network('test nodes network')
    ed.addNetwork(net)
    ed.setNetwork(net)

    # test all nodes in stdlib
    posx = 150
    posy = 150
    stdlib = ed.libraries['Standard']
    
    for cat in stdlib.libraryDescr.keys():
        for node in stdlib.libraryDescr[cat]['nodes']:
            klass = node.nodeClass
            kw = node.kw
            args = node.args
            netNode = apply( klass, args, kw )
            print 'testing: '+node.name # begin node test
            #add node to canvas
            ed.currentNetwork.addNode(netNode,posx,posy)
            # show widget in node if available:
            widgetsInNode = netNode.getWidgetsForMaster('Node')
            if len(widgetsInNode.items()) is not None:
                for port,widget in widgetsInNode.items():
                    netNode.createOneWidget(port)
                    ed.root.update_idletasks()
                # and then hide it
                for port,widget in widgetsInNode.items():
                    netNode.hideInNodeWidget(port.widget)
                    ed.root.update_idletasks()

            # show widgets in param panel if available:
            widgetsInPanel = netNode.getWidgetsForMaster('ParamPanel')
            if len(widgetsInPanel.items()):
                netNode.paramPanel.show()
                ed.root.update_idletasks()

                #and then hide it
                netNode.paramPanel.hide()
                ed.root.update_idletasks()

            # and now delete the node
            ed.currentNetwork.deleteNodes([netNode])
            ed.root.update_idletasks()

            print 'passed: '+node.name # end node test
    # and delete this network
    ed.deleteNetwork(ed.networks['test nodes network'])


def test_runNetworkWithoutNodes():
    from NetworkEditor.net import Network
    net = Network('run network with no nodes')
    ed.addNetwork(net)
    ed.setNetwork(net)
    net.run()
    pause()
    ed.deleteNetwork(ed.networks['run network with no nodes'])
 

def test_runCurrentNetwork():
    ed.loadNetwork('forLoop_net.py')
    ed.currentNetwork.run()
    ed.runCurrentNet_cb()
    pause()
    ed.deleteNetwork(ed.networks['forLoop'])


def test_runNotCurrentNetwork():
    ed.loadNetwork('forLoop_net.py')

    # load second network which becomes the current network
    ed.loadNetwork('dial_net.py')
    pause()

    # load same network again
    ed.loadNetwork('forLoop_net.py', name='forLoopCopy')
    pause()

    # run the firs network while it is not current
    ed.networks['dial'].run()
    pause()

    ed.deleteNetwork(ed.networks['forLoop'])
    ed.deleteNetwork(ed.networks['dial'])
    ed.deleteNetwork(ed.networks['forLoopCopy'])


def test_mergeNetwork():
    # load dial network
    ed.loadNetwork('dial_net.py')
    # load forLoop network and merge it into the dial network
    ed.loadNetwork('forLoop_net.py', ed.networks['dial'])
    # make the dial network current so we can see what happened
    ed.setNetwork(ed.networks['dial'])
    pause()
    ed.deleteNetwork(ed.networks['dial'])

    
def test_renameNetwork():
    ed.loadNetwork('dial_net.py')
    net = ed.networks['dial']
    net.rename('dialRenamed')

    print ed.networks

    assert 'dial' not in ed.networks.keys()
    assert 'dialRenamed' in ed.networks.keys()
    
    newnet = ed.networks['dialRenamed']

    pause()
    ed.deleteNetwork(newnet)    


harness = testplus.TestHarness( "Vision",
                                connect = (startEditor, (), {}),
                                funs = testplus.testcollect( globals()),
                                disconnect = quitEditor
                                )

if __name__ == '__main__':
    testplus.chdir()
    print harness
    sys.exit( len( harness))
