#########################################################################
#
# Date: Aug 2003  Authors: Daniel Stoffler, Michel Sanner
#
#       sanner@scripps.edu
#       stoffler@scripps.edu
#
#       The Scripps Research Institute (TSRI)
#       Molecular Graphics Lab
#       La Jolla, CA 92037, USA
#
# Copyright: Daniel Stoffler, Michel Sanner, and TSRI
#
#########################################################################


from time import sleep
import os

from NetworkEditor.net import Network
from NetworkEditor.simpleNE import NetworkNode, NetworkBuilder
from NetworkEditor.Tests.nodes import DialNode, PrintNode, PassNode


ed = None
def setUp():
    global ed
    ed = NetworkBuilder("test builder1", withShell=0,
                        visibleWidth=400, visibleHeight=300)
    ed.master.update()
    ed.configure(withThreads=0)


def tearDown():
    ed.exit_cb()
    import gc
    gc.collect()
    
##########################
## Helper methods
##########################
def pause(sleepTime=None):
    if sleepTime is None:
        from NetworkEditor.Tests import pauseLength as sleepTime
    ed.master.update()
    sleep(sleepTime)


##########################
## Tests
##########################

def test_000_openNodeEditor():
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    pause()
    from NetworkEditor.Editor import NodeEditor
    assert isinstance(n.objEditor, NodeEditor),\
           "Expexted %s, got %s"%(NodeEditor, n.objEditor.__class__)
    n.objEditor.Dismiss()
    assert n.objEditor == None,"Expected None, got %s"%n.objEditor


def test_001_renameNodeOK():
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    n.objEditor.nameTk.set('New Name')
    pause()
    n.objEditor.OK()
    assert n.name == 'New Name',"Expected 'New Name', got '%s'"%n.name
    assert n.network.canvas.itemconfig(n.textId)['text'][4]==('New', 'Name'),\
           "Expected ('New', 'Name'), got %s"%n.network.canvas.itemconfig(n.textId)['text'][4]


def test_002_renameNodeApply():
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    n.objEditor.nameTk.set('New Name')
    pause()
    n.objEditor.Apply()
    assert n.name == 'New Name',"Expected 'New Name', got '%s'"%n.name
    assert n.network.canvas.itemconfig(n.textId)['text'][4]==('New', 'Name'),\
           "Expected ('New', 'Name'), got %s"%n.network.canvas.itemconfig(n.textId)['text'][4]           


def test_003_renameNodeDismiss():
    n = NetworkNode('DoNotChangeMyName')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    n.objEditor.nameTk.set('New Name')
    pause()
    n.objEditor.Dismiss()
    assert n.name == 'DoNotChangeMyName',\
           "Expected 'DoNotChangeMyName', got %s"%n.name
    assert n.network.canvas.itemconfig(n.textId)['text'][4]==\
           'DoNotChangeMyName',\
           "Expected 'DoNotChangeMyName', got '%s'"%n.network.canvas.itemconfig(n.textId)['text'][4]

def test_004_RenameSaveAndReload():
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    n.objEditor.nameTk.set('New Name')
    pause()
    n.objEditor.OK()
    os.system("rm -f a_net.py*")
    # save network and reaload it
    ed.saveNetwork('a_net.py')
    ed.delete()
    ed.loadNetwork('a_net.py')
    n = ed.currentNetwork.nodes[0]
    assert n.name == 'New Name',"Expected 'New Name', got '%s'"%n.name
    assert n.network.canvas.itemconfig(n.textId)['text'][4]==('New', 'Name'),\
           "Expected ('New', 'Name'), got %s"%n.network.canvas.itemconfig(n.textId)['text'][4]   
    #clean up temporary network file
    os.system("rm -f a_net.py*")


def test_005_addInputPort():
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    lp = len(n.inputPorts)
    n.objEditor.newInputPort()
    p = n.inputPorts[-1]
    pause()
    assert len(n.inputPorts) == lp+1,\
           "Expected %s, got %s"%(lp+1, len(n.inputPorts))
    assert len(n.inputPortsDescr) == 1,\
           "Expected 1, got %s"%len(n.inputPortsDescr)
    assert p._modified == True,"Expected True, got %s"%p._modified

    import Tkinter
    assert isinstance( p.portEditCB, Tkinter.Checkbutton),\
           "Expected %s, got %s"%(Tkinter.Checkbutton, p.portEditCB.__class__)
    assert isinstance( p.portDelCB, Tkinter.Checkbutton),\
           "Expecyed %s, got %s"%(Tkinter.Checkbutton, p.portDelCB.__class__)

    sig = n.sourceCode.split('\n')
    assert p.name in sig[0],"p.name is: %s; sig[0] contains: %s"%(
        p.name, sig[0])

    # save network and reload it, make sure port modification will survive
    # next save operation
    os.system("rm -f a_net.py*")
    ed.saveNetwork('a_net.py')
    ed.deleteNetwork(ed.currentNetwork)
    ed.loadNetwork('a_net.py')
    n = ed.currentNetwork.nodes[0]
    assert len(n.inputPorts) == lp+1,\
           "Expected %s, got %s"%(lp+1, len(n.inputPorts))
    assert len(n.inputPortsDescr) == 1,\
           "Expected 1, got %s"%len(n.inputPortsDescr)
    p = n.inputPorts[-1]
    sig = n.sourceCode.split('\n')
    assert p.name in sig[0], "p.name is: %s; sig[0] contains: %s"%(
        p.name, sig[0])
    #clean up temporary network file
    os.system("rm -f a_net.py*")


def test_006_addOutputPort():
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    lp = len(n.outputPorts)
    n.objEditor.newOutputPort()
    p = n.outputPorts[-1]
    pause()
    assert len(n.outputPorts) == lp+1,\
           "Expected %s, got %s"%(lp+1, len(n.outputPorts))
    assert len(n.outputPortsDescr) == 1,\
           "Expected 1, got %s"%len(n.outputPortsDescr)
    assert p._modified == True,\
           "Expected True, got %s"%p._modified
    import Tkinter
    assert isinstance( p.portEditCB, Tkinter.Checkbutton),\
           "Expected %s, got %s"%(Tkinter.Checkbutton, p.portEditCB.__class__)
    assert isinstance( p.portDelCB, Tkinter.Checkbutton),\
           "Expecyed %s, got %s"%(Tkinter.Checkbutton, p.portDelCB.__class__)
    # save network and reload it, make sure port modification will survive
    # next save operation
    os.system("rm -f a_net.py*")
    ed.saveNetwork('a_net.py')
    ed.delete()
    ed.loadNetwork('a_net.py')
    n = ed.currentNetwork.nodes[0]
    assert len(n.outputPorts) == lp+1,\
           "Expected %s, got %s"%(lp+1, len(n.outputPorts))
    assert len(n.outputPortsDescr) == 1,\
           "Expected 1, got %s"%len(n.outputPortsDescr)
    p = n.outputPorts[-1]
    #clean up temporary network file
    os.system("rm -f a_net.py*")


def test_007_deleteInputPort():
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    lp = len(n.inputPorts)
    n.objEditor.newInputPort()
    pause()
    assert n.inputPorts[-1].node == n,\
           "Expected %s, got %s"%(n, n.inputPorts[-1].node)
    assert n.inputPorts[-1].network == n.network,\
           "Expected %s, got %s"%(n.network, n.inputPorts[-1].network)
    assert n.inputPorts[-1].getEditor() == n.getEditor(),\
           "Expected %s, got %s"%(n.getEditor(), n.inputPorts[-1].getEditor())
    
    n.objEditor.newInputPort()
    n.objEditor.newInputPort()
    p = n.inputPorts[-1]
    assert len(n.inputPorts) == lp+3,\
           "Expected %s, got %s"%(lp+3, len(n.inputPorts))
    assert len(n.inputPortsDescr) == 3,\
           "Expected 3, got %s"%len(n.inputPortsDescr)
    assert n.inputPorts[0].name == 'in0',\
           "Expected 'in0', got '%s'"%n.inputPorts[0].name
    assert n.inputPorts[1].name == 'in1',\
           "Expected 'in1', got '%s'"%n.inputPorts[1].name
    assert n.inputPorts[2].name == 'in2',\
           "Expected 'in2', got '%s'"%n.inputPorts[2].name

    sig = n.sourceCode.split('\n')
    assert 'def doit(self, in0, in1, in2):' in sig[0],\
           "sig[0] contains: %s"%sig[0]

    p = n.inputPorts[1]
    n.objEditor.deletePort(p)
    pause()
    assert len(n.inputPorts) == lp+2,\
           "Expected %s, got %s"%(lp+2, len(n.inputPorts))
    assert len(n.inputPortsDescr) == 2,\
           "Expected 2, got %s"%len(n.inputPortsDescr)
    assert n.inputPorts[0].name == 'in0',\
           "Expected 'in0', got '%s'"%n.inputPorts[0].name
    assert n.inputPorts[1].name == 'in2',\
           "Expected 'in2', got '%s'"%n.inputPorts[1].name

    sig = n.sourceCode.split('\n')
    assert 'def doit(self, in0, in2):' in sig[0],\
           "sig[0] contains: %s"%sig[0]


def test_008_deleteOutputPort():
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    lp = len(n.outputPorts)
    n.objEditor.newOutputPort()
    assert n.outputPorts[-1].node == n,\
           "Expected %s, got %s"%(n, n.outputPorts[-1].node)    
    assert n.outputPorts[-1].network == n.network,\
           "Expected %s, got %s"%(n.network, n.outputPorts[-1].network)
    assert n.outputPorts[-1].getEditor() == n.getEditor(),\
           "Expected %s, got %s"%(n.getEditor(), n.outputPorts[-1].getEditor())
    n.objEditor.newOutputPort()
    pause()
    n.objEditor.newOutputPort()
    p = n.outputPorts[-1]
    pause()
    assert len(n.outputPorts) == lp+3,\
           "Expected %s, got %s"%(lp+3, len(n.outputPorts))
    assert len(n.outputPortsDescr) == 3
    assert n.outputPorts[0].name == 'out0',\
           "Expected 'out0', got '%s'"%n.outputPorts[0].name
    assert n.outputPorts[1].name == 'out1',\
           "Expected 'out1', got '%s'"%n.outputPorts[1].name
    assert n.outputPorts[2].name == 'out2',\
           "Expected 'out2', got '%s'"%n.outputPorts[2].name

    p = n.outputPorts[1]
    n.objEditor.deletePort(p)
    pause()
    assert len(n.outputPorts) == lp+2,\
           "Expected %s, got %s"%(lp+2, len(n.outputPorts))
    assert len(n.outputPortsDescr) == 2,\
           "Expected 2, got %s"%len(n.outputPortsDescr)
    assert n.outputPorts[0].name == 'out0',\
           "Expected 'in0', got '%s'"%n.outputPorts[0].name
    assert n.outputPorts[1].name == 'out2',\
           "Expected 'in2', got '%s'"%n.outputPorts[1].name


def test_009_startStopCodeEditorFromNodeEditor():
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    n.objEditor.editButtonVarTk.set(1)
    n.objEditor.editFunction_cb()
    pause()
    assert n.objEditor.nbEditorWindows == 1,\
           "Expected 1, got %s"%n.objEditor.nbEditorWindows
    assert n.objEditor.editButtonVarTk.get() == 1,\
           "Expected 1, got %s"%n.objEditor.editButtonVarTk
    assert n.objEditor.applyButton.cget('state') == 'disabled',\
          "Expected 'disabled', got '%s'"%n.objEditor.applyButton.cget('state')
    assert n.objEditor.okButton.cget('state') == 'disabled',\
           "Expected 'disabled', got '%s'"%n.objEditor.okButton.cget('state')
    assert n.objEditor.cancelButton.cget('state') == 'disabled',\
         "Expected 'disabled', got '%s'"%n.objEditor.cancelButton.cget('state')

    # invoke apply
    n.objEditor.funcEditorDialog.applyCmd()
    assert n.objEditor.nbEditorWindows == 1,\
           "Expected 1, got %s"%n.objEditor.nbEditorWindows
    assert n.objEditor.editButtonVarTk.get() == 1,\
           "Expected 1, got %s"%n.objEditor.editButtonVarTk.get()
    assert n.objEditor.applyButton.cget('state') == 'disabled',\
          "Expected 'disabled', got '%s'"%n.objEditor.applyButton.cget('state')
    assert n.objEditor.okButton.cget('state') == 'disabled',\
           "Expected 'disabled', got '%s'"%n.objEditor.okButton.cget('state')
    assert n.objEditor.cancelButton.cget('state') == 'disabled',\
         "Expected 'disabled', got '%s'"%n.objEditor.cancelButton.cget('state')
    # invoke apply
    n.objEditor.funcEditorDialog.okCmd()
    assert n.objEditor.nbEditorWindows == 0,\
           "Expected 0, got %s"%n.objEditor.nbEditorWindows
    assert n.objEditor.editButtonVarTk.get() == 0,\
           "Expected 0, got %s"%n.objEditor.editButtonVarTk.get()
    assert n.objEditor.applyButton.cget('state') == 'normal',\
           "Expected 'normal', got '%s'"%n.objEditor.applyButton.cget('state')
    assert n.objEditor.okButton.cget('state') == 'normal',\
           "Expected 'normal', got '%s'"%n.objEditor.okButton.cget('state')
    assert n.objEditor.cancelButton.cget('state') == 'normal',\
           "Expected 'normal', got '%s'"%n.objEditor.cancelButton.cget('state')


def test_010_bindWidgetThenDeletePort():
    # this tests if we can bind a widget to a port, then delete the port
    n = NetworkNode('Test Node')
    ed.currentNetwork.addNode(n, 100, 50)
    n.edit()
    # add new input port
    n.objEditor.newInputPort()
    p = n.inputPorts[-1]
    # no widget, so no edit widget checkbutton
    assert p.editWtk is None,"Expected None, got %s"%p.editWtk
    # start port editor
    p.edit()
    # bind widget
    p.objEditor.widgetType.selectitem("NEDial")
    pause()
    p.objEditor.Apply()
    p.objEditor.Cancel()
    from NetworkEditor.widgets import NEDial
    assert p.widget is not None, "p.widget is %s"%p.widget
    assert p.widget.__class__ == NEDial,\
           "Expected %s, got %s"%(NEDial, p.widget.__class__)
    assert p.visible == 0,"Expected 0, got %s"%p.visible
    # edit widget checkbutton should be bound
    assert p.editWtk is not None, "p.editWtk is %s"%p.editWtk
    from Tkinter import Checkbutton
    assert p.editWtk.__class__ == Checkbutton,\
           "Expected %s, got %s"%(Checkbutton, p.editWtk)
    # delete port (this should not raise any exceptions of course)
    n.objEditor.deletePort(p)
    
