"""
Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)

Model author: Sam Pieters
Model name:   Timer (Eventloop Version)

"""

from sccd.runtime.statecharts_core import *
from sccd.runtime.libs.ui import ui
import time

CANVAS_WIDTH = 350
CANVAS_HEIGHT = 300

# package "Timer (Eventloop Version)"

class MainApp(RuntimeClassBase):
    def __init__(self, controller):
        RuntimeClassBase.__init__(self, controller)
        
        self.inports["field_ui"] = controller.addInputPort("field_ui", self)
        
        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
        self.semantics.priority = StatechartSemantics.SourceParent
        self.semantics.concurrency = StatechartSemantics.Single
        
        # build Statechart structure
        self.build_statechart_structure()
        
        # user defined attributes
        self.window_id = None
        self.canvas_id = None
        self.clock_id = None
        self.actual_clock_id = None
        self.button_id = None
        self.starting_time = None
        
        # call user defined constructor
        MainApp.user_defined_constructor(self)
    
    def user_defined_constructor(self):
        pass
    
    def user_defined_destructor(self):
        pass
    
    
    # builds Statechart structure
    def build_statechart_structure(self):
        
        # state <root>
        self.states[""] = State(0, "", self)
        
        # state /creating_window
        self.states["/creating_window"] = State(1, "/creating_window", self)
        self.states["/creating_window"].setEnter(self._creating_window_enter)
        
        # state /creating_canvas
        self.states["/creating_canvas"] = State(2, "/creating_canvas", self)
        self.states["/creating_canvas"].setEnter(self._creating_canvas_enter)
        
        # state /creating_clock_text
        self.states["/creating_clock_text"] = State(3, "/creating_clock_text", self)
        self.states["/creating_clock_text"].setEnter(self._creating_clock_text_enter)
        
        # state /creating_actual_clock_text
        self.states["/creating_actual_clock_text"] = State(4, "/creating_actual_clock_text", self)
        self.states["/creating_actual_clock_text"].setEnter(self._creating_actual_clock_text_enter)
        
        # state /creating_interrupt_button
        self.states["/creating_interrupt_button"] = State(5, "/creating_interrupt_button", self)
        self.states["/creating_interrupt_button"].setEnter(self._creating_interrupt_button_enter)
        
        # state /running
        self.states["/running"] = State(6, "/running", self)
        self.states["/running"].setEnter(self._running_enter)
        self.states["/running"].setExit(self._running_exit)
        
        # state /interrupted
        self.states["/interrupted"] = State(7, "/interrupted", self)
        
        # add children
        self.states[""].addChild(self.states["/creating_window"])
        self.states[""].addChild(self.states["/creating_canvas"])
        self.states[""].addChild(self.states["/creating_clock_text"])
        self.states[""].addChild(self.states["/creating_actual_clock_text"])
        self.states[""].addChild(self.states["/creating_interrupt_button"])
        self.states[""].addChild(self.states["/running"])
        self.states[""].addChild(self.states["/interrupted"])
        self.states[""].fixTree()
        self.states[""].default_state = self.states["/creating_window"]
        
        # transition /creating_window
        _creating_window_0 = Transition(self, self.states["/creating_window"], [self.states["/creating_canvas"]])
        _creating_window_0.setAction(self._creating_window_0_exec)
        _creating_window_0.setTrigger(Event("window_created", None))
        self.states["/creating_window"].addTransition(_creating_window_0)
        
        # transition /creating_canvas
        _creating_canvas_0 = Transition(self, self.states["/creating_canvas"], [self.states["/creating_clock_text"]])
        _creating_canvas_0.setAction(self._creating_canvas_0_exec)
        _creating_canvas_0.setTrigger(Event("canvas_created", None))
        self.states["/creating_canvas"].addTransition(_creating_canvas_0)
        
        # transition /creating_clock_text
        _creating_clock_text_0 = Transition(self, self.states["/creating_clock_text"], [self.states["/creating_actual_clock_text"]])
        _creating_clock_text_0.setAction(self._creating_clock_text_0_exec)
        _creating_clock_text_0.setTrigger(Event("text_created", None))
        self.states["/creating_clock_text"].addTransition(_creating_clock_text_0)
        
        # transition /creating_actual_clock_text
        _creating_actual_clock_text_0 = Transition(self, self.states["/creating_actual_clock_text"], [self.states["/creating_interrupt_button"]])
        _creating_actual_clock_text_0.setAction(self._creating_actual_clock_text_0_exec)
        _creating_actual_clock_text_0.setTrigger(Event("text_created", None))
        self.states["/creating_actual_clock_text"].addTransition(_creating_actual_clock_text_0)
        
        # transition /creating_interrupt_button
        _creating_interrupt_button_0 = Transition(self, self.states["/creating_interrupt_button"], [self.states["/running"]])
        _creating_interrupt_button_0.setAction(self._creating_interrupt_button_0_exec)
        _creating_interrupt_button_0.setTrigger(Event("button_created", None))
        self.states["/creating_interrupt_button"].addTransition(_creating_interrupt_button_0)
        
        # transition /running
        _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
        _running_0.setAction(self._running_0_exec)
        _running_0.setTrigger(Event("_0after"))
        self.states["/running"].addTransition(_running_0)
        _running_1 = Transition(self, self.states["/running"], [self.states["/interrupted"]])
        _running_1.setTrigger(Event("mouse_click", self.getInPortName("field_ui")))
        _running_1.setGuard(self._running_1_guard)
        self.states["/running"].addTransition(_running_1)
        
        # transition /interrupted
        _interrupted_0 = Transition(self, self.states["/interrupted"], [self.states["/running"]])
        _interrupted_0.setTrigger(Event("mouse_click", self.getInPortName("field_ui")))
        _interrupted_0.setGuard(self._interrupted_0_guard)
        self.states["/interrupted"].addTransition(_interrupted_0)
    
    def _creating_window_enter(self):
        self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [CANVAS_WIDTH, CANVAS_HEIGHT, "Fixed Timer", self.inports['field_ui']]))
    
    def _creating_canvas_enter(self):
        self.big_step.outputEvent(Event("create_canvas", self.getOutPortName("ui"), [self.window_id, CANVAS_WIDTH, CANVAS_HEIGHT - 200, {'background':'#222222'}, self.inports['field_ui']]))
    
    def _creating_clock_text_enter(self):
        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, 50, 50, '', self.inports['field_ui']]))
    
    def _creating_actual_clock_text_enter(self):
        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, 50, 100, '', self.inports['field_ui']]))
    
    def _creating_interrupt_button_enter(self):
        self.big_step.outputEvent(Event("create_button", self.getOutPortName("ui"), [self.window_id, 'INTERRUPT/CONTINUE', self.inports['field_ui']]))
    
    def _running_enter(self):
        self.addTimer(0, 0.05)
    
    def _running_exit(self):
        self.removeTimer(0)
    
    def _creating_window_0_exec(self, parameters):
        window_id = parameters[0]
        self.window_id = window_id
        self.starting_time = time.time()
        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.WINDOW_CLOSE, 'window_close', self.inports['field_ui']]))
        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.KEY_PRESS, 'key_press', self.inports['field_ui']]))
    
    def _creating_canvas_0_exec(self, parameters):
        canvas_id = parameters[0]
        self.canvas_id = canvas_id
    
    def _creating_clock_text_0_exec(self, parameters):
        canvas_id = parameters[0]
        text_id = parameters[1]
        self.clock_id = text_id
    
    def _creating_actual_clock_text_0_exec(self, parameters):
        canvas_id = parameters[0]
        text_id = parameters[1]
        self.actual_clock_id = text_id
    
    def _creating_interrupt_button_0_exec(self, parameters):
        button_id = parameters[0]
        self.button_id = button_id
        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [button_id, ui.EVENTS.MOUSE_CLICK, "mouse_click", self.inports['field_ui']]))
    
    def _running_0_exec(self, parameters):
        self.big_step.outputEvent(Event("update_text", self.getOutPortName("ui"), [self.canvas_id, self.clock_id, str('%.2f' % (self.getSimulatedTime() / 1000.0)), self.inports['field_ui']]))
        self.big_step.outputEvent(Event("update_text", self.getOutPortName("ui"), [self.canvas_id, self.actual_clock_id, str('%.2f' % (time.time() - self.starting_time)), self.inports['field_ui']]))
    
    def _running_1_guard(self, parameters):
        x = parameters[0]
        y = parameters[1]
        button = parameters[2]
        return button == ui.MOUSE_BUTTONS.LEFT
    
    def _interrupted_0_guard(self, parameters):
        x = parameters[0]
        y = parameters[1]
        button = parameters[2]
        return button == ui.MOUSE_BUTTONS.LEFT
    
    def initializeStatechart(self):
        # enter default state
        self.default_targets = self.states["/creating_window"].getEffectiveTargetStates()
        RuntimeClassBase.initializeStatechart(self)

class ObjectManager(ObjectManagerBase):
    def __init__(self, controller):
        ObjectManagerBase.__init__(self, controller)
    
    def instantiate(self, class_name, construct_params):
        if class_name == "MainApp":
            instance = MainApp(self.controller)
            instance.associations = {}
        else:
            raise Exception("Cannot instantiate class " + class_name)
        return instance

class Controller(EventLoopControllerBase):
    def __init__(self, event_loop_callbacks, finished_callback = None, behind_schedule_callback = None):
        if finished_callback == None: finished_callback = None
        if behind_schedule_callback == None: behind_schedule_callback = None
        EventLoopControllerBase.__init__(self, ObjectManager(self), event_loop_callbacks, finished_callback, behind_schedule_callback)
        self.addInputPort("ui")
        self.object_manager.createInstance("MainApp", [])