from pypdevs.DEVS import AtomicDEVS, CoupledDEVS
from pypdevs.simulator import Simulator
from pypdevs.infinity import INFINITY

import Tkinter as tk
from Queue import Empty
from ast import literal_eval as make_tuple

class Window(tk.Toplevel):
    def __init__(self, sim):
        tk.Toplevel.__init__(self)
				
        CANVAS_SIZE_TUPLE = (0, 0, self.winfo_screenwidth(), self.winfo_screenheight())
        self.canvas = tk.Canvas(self, relief=tk.RIDGE, scrollregion=CANVAS_SIZE_TUPLE)        
        self.canvas.bind("<Button-1>", self.callback)
        self.canvas.pack(expand = True, fill=tk.BOTH)
        
        self.sim = sim
        self.after(5, self.check_output)
    
    def callback(self, event):
        print 'Clicked (%i,%i)' % (event.x, event.y)
        self.sim.realtime_interrupt("INTERRUPT (%i,%i)" % (event.x, event.y))
    
    def check_output(self):
        while True:
            try:
                print self.sim.model.out_msg_queue.get(False)
            except Empty:
                break
        self.after(5, self.check_output)

class CoupledModel(CoupledDEVS):
    def __init__(self):
        CoupledDEVS.__init__(self, "CoupledModel")
        self.INTERRUPT = self.addInPort("INTERRUPT")
        self.UICOMM = self.addOutPort("UICOMM")
        self.model = self.addSubModel(Model())
        self.connectPorts(self.INTERRUPT, self.model.INTERRUPT)
        self.connectPorts(self.model.UICOMM, self.UICOMM)

class Model(AtomicDEVS):
    def __init__(self):
        AtomicDEVS.__init__(self, "Model")
        self.INTERRUPT = self.addInPort("INTERRUPT")
        self.UICOMM = self.addOutPort("UICOMM")
        self.remaining = 1
    
    def outputFnc(self):
        return {self.UICOMM: ["MyMessage"]}

    def intTransition(self):
        print 'Working...'
        self.remaining = 1
    
    def extTransition(self, inputs):
        self.remaining -= self.elapsed
        self.click_pos = make_tuple(inputs[self.INTERRUPT][0])
        print 'Interrupted (%i,%i)' % self.click_pos
    
    def timeAdvance(self):
        return self.remaining

if __name__ == '__main__':
    root = tk.Tk()
    root.withdraw()
    
    model = CoupledModel()
    
    sim = Simulator(model)
    sim.setRealTime(True)
    sim.setRealTimeInputFile(None)
    sim.setRealTimePorts({'INTERRUPT': model.INTERRUPT})
    sim.setRealTimePlatformTk(root)
    sim.setDSDEVS(True)
    sim.setClassicDEVS(True)
    sim.setTerminationTime(30)
    
    window = Window(sim)
    
    sim.simulate()
    root.mainloop()