import sys, string
from time import sleep
from mglutil.regression import testplus
from ViPEr.StandardNodes import Eval, DialNE, Counter, Pass, Print, Iterate
from NetworkEditor.net import Network
from NetworkEditor.simpleNE import NetworkBuilder

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
    ed = NetworkBuilder("test builder1", withShell=0,
                        visibleWidth=400, visibleHeight=300)
    ed.master.update()
    ed.configure(withThreads=withThreads)


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


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


def test_runNetwork():
    net = Network('runNetwork')
    ed.addNetwork(net)
    ed.setNetwork(net)
    node1 = DialNE()
    net.addNode(node1, 50, 50)
    pause()
    assert node1.outputPorts[0].data is None
    net.run()
    assert node1.outputPorts[0].data is not None
    ed.deleteNetwork(net)
    

def test_runNode():
    net = Network('runNode')
    ed.addNetwork(net)
    ed.setNetwork(net)
    node1 = DialNE()
    net.addNode(node1, 50, 50)
    pause()
    assert node1.outputPorts[0].data is None
    node1.run()
    assert node1.outputPorts[0].data is not None
    ed.deleteNetwork(net)
    

def test_scheduleNode():
    net = Network('scheduleNode')
    ed.addNetwork(net)
    ed.setNetwork(net)
    node1 = DialNE()
    net.addNode(node1, 50, 50)
    pause()
    assert node1.outputPorts[0].data is None
    node1.schedule()
    assert node1.outputPorts[0].data is not None
    ed.deleteNetwork(net)
    

#def test_freezeNetwork():
#    net = Network('freezeNetwork')
#    ed.addNetwork(net)
#    ed.setNetwork(net)
#    node1 = Eval()
#    net.addNode(node1, 50, 50)
#    node1.toggleNodeExpand_cb()
#    # freeze network
#    net.freeze()
#    pause()
#    net.run()
#    node1.inputPorts[0].widget.set('range(2000)')
#    assert node1.outputPorts[0].data is None
#    net.unfreeze()
#    pause()
#    assert net.execStatus=='waiting'
#    assert node1.outputPorts[0].data is None
#
#    net.freeze(updateGUI=1)
#    assert node1.network.canvas.itemconfig(node1.id)['fill'][-1]=='blue'
#    net.unfreeze(updateGUI=1)
#    assert node1.network.canvas.itemconfig(node1.id)['fill'][-1]=='gray85'
#
#    # use editor call to freeze
#    ed.freezeNetwork()
#    pause()
#    assert ed.isFrozenTk.get()==1
#    assert node1.network.canvas.itemconfig(node1.id)['fill'][-1]=='blue'
#    node1.inputPorts[0].widget.set('range(200)')
#    assert node1.outputPorts[0].data is None
#    ed.unfreezeNetwork()
#    pause()
#    assert ed.isFrozenTk.get()==0
#    assert node1.network.canvas.itemconfig(node1.id)['fill'][-1]=='gray85'
#    #This triggers the execution
#    assert node1.outputPorts[0].data is None
#
#    # add second network
#    ed.freezeNetwork()
#    pause()
#    net1 = Network('freeze1Network')
#    ed.addNetwork(net1)
#    ed.setNetwork(net1)
#    assert ed.isFrozenTk.get()==0
#
#    node2 = DialNE()
#    net1.addNode(node2, 50, 50)
#    node2.inputPorts[0].widget.set(100, run=1)
#    pause()
#    assert node2.outputPorts[0].data == 100
#    ed.deleteNetwork(net1)
#
#    # got back to first network
#    assert ed.isFrozenTk.get()==1
#    ed.deleteNetwork(net)


def test_setWidgetValue():
    # add a dial node, set it's value to 10.0 and see if the node outputs
    net = Network('setWidgetValue')
    ed.addNetwork(net)
    ed.setNetwork(net)
    node1 = DialNE()
    net.addNode(node1, 50, 50)
    out = node1.outputPorts[0]
    # should not output any data right now
    assert out.data is None
    dial1 = node1.inputPorts[0].widget
    dial1.set(10.0)
    # now the output port should have data
    assert out.data == 10.0
    ed.deleteNetwork(net)
   

def test_runChildUponConnect():
    # add a dial node, set it's value to 10.0, connect a Pass node and see if
    # the Pass node outputs 10.0
    net = Network('runChildUponConnect')
    ed.addNetwork(net)
    ed.setNetwork(net)
    node1 = DialNE()
    net.addNode(node1, 50, 50)
    dial1 = node1.inputPorts[0].widget
    dial1.set(10.0)
    # now connect a Pass node and check if its output port has 10.0
    node2 = Pass()
    net.addNode(node2, 50, 150)
    net.connectNodes(node1, node2, 0, 0)
    pause()
    assert node2.outputPorts[0].data == [10.0]
    ed.deleteNetwork(net)


def test_TriggerOutputPort():
    # test execution of special ports: a network with a dial1 node and
    # a dial2 node connected to a Counter node. Then we connect special
    # outputport of dial1 to the special input port of Counter and run
    # dial1 (not dial2), which should trigger the counter node to run again
    net = Network('TriggerOutputPort')
    ed.addNetwork(net)
    ed.setNetwork(net)
    node1 = DialNE()
    net.addNode(node1, 50, 50)
    pause()
    dial1 = node1.inputPorts[0].widget
    dial1.set(10.0)
    node2 = DialNE()
    net.addNode(node2, 150, 50)
    node3 = Counter()
    net.addNode(node3, 150, 150)
    net.connectNodes(node2, node3, 0, 0)
    dial2 = node2.inputPorts[0].widget
    # set dial2, which should increase the counter node by 1
    dial2.set(20.0)
    assert node3.counter == 1
    pause()
    # show special ports on dial 1 and counter
    node1.showSpecialPorts()
    node3.showSpecialPorts()
    # connect dial1 with counter
    net.specialConnectNodes(node1, node3, 0, 0)
    pause()
    # counter should still be 1
    assert node3.counter == 1
    # now change value in dial1 which should trigger specialoutputport
    dial1.set(15.0)
    assert node3.counter == 2
    ed.deleteNetwork(net)


def test_basicScheduling():
    net = Network('basicScheduling')
    ed.addNetwork(net)
    ed.setNetwork(net)

    net = ed.currentNetwork
    node1 = Eval()
    net.addNode(node1, 50, 50)
    node2 = Iterate()
    net.addNode(node2, 50, 150)
    node3 = Print()
    net.addNode(node3, 50, 250)

    net.connectNodes(node1, node2, 0, 0 )
    net.connectNodes(node2, node3, 0, 0 )

    # stop node execution
    net.stop()
    assert net.execStatus == 'stop'

    # pause node execution
    net.pause()
    assert net.execStatus == 'pause'

    # resume node execution
    net.resume()
    assert net.execStatus == 'running'

    # start node execution
    net.start()
    assert net.execStatus == 'pending'
    
    # show the widget in node1
    node1.toggleNodeExpand_cb()
    node1.inputPorts[0].widget.set('range(20)')

    # run network that fails
    net.run()

    # run network that should run
    node1.inputPorts[0].widget.set('range(20)')

    # run long execution
    node1.inputPorts[0].widget.set('range(400)', run=0)
    net.run()
    pause(0.1)
    net.pause()
    pause(0.1)
    net.resume()
    pause(0.1)
    net.stop()
    ed.deleteNetwork(net)
    

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

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