import time
import threading
import Queue

quit = False
event_queue = None

class Event:
  def __init__(self, name):
    self.name = name


class State:
    def __init__(self):
      self.name = ''
      self.transitions = {}

    def add_transition(self, toState, callback):
      self.transitions[toState] = callback

class EventFsm:
    def __init__(self):
        self.states = {}
        self.startState = None
        self.currentState = None

    def add_state(self, name):
        a_state = State()
        a_state.name = name
        self.states[name] = a_state
        return a_state

    def set_start(self, name):
        self.startState = name

    def set_current(self, name):
        self.currentState = name


    def run(self):
      while not quit:
        if event_queue:
          event = event_queue.get()
          if event.name in self.currentState.transitions:
            self.currentState.transitions[event]()
            self.set_current(event.name)
        time.sleep(1)

def foo_to_bar():
  print "transition foo -> bar"

def foo_to_baz():
  print "transition foo -> baz" 

def bar_to_foo():
  print "transition bar -> foo"

def baz_to_bar():
  print "transition baz -> bar"

def baz_to_fee():
  print "transition baz -> fee"

def fee_to_baz():
  print "transition fee -> baz"

def fee_to_foo():
  print "transition fee -> foo"

def monitor_events():
  global event_queue
  events = ["foo", "bar", "baz", "fee"]
  while not quit:
    event = Event(random.choice(events))
    event_queue.put(event)
    time.sleep(1)

def build_states(fsm):
  state_foo = fsm.add_state("foo")
  state_bar = fsm.add_state("bar")
  state_baz = fsm.add_state("baz")
  state_fee = fsm.add_state("fee")

  state_foo.add_transition("bar", foo_to_bar)
  state_foo.add_transition("baz", foo_to_baz)

  state_bar.add_transition("foo", bar_to_foo)

  state_baz.add_transition("bar", baz_to_bar)
  state_baz.add_transition("fee", baz_to_fee)

  state_fee.add_transition("baz", fee_to_baz)
  state_fee.add_transition("foo", fee_to_foo)

def main():
    global event_queue
    event_queue = Queue.Queue()

    fsm = EventFsm()
    print "created a state machine"
    build_states(fsm)

    fsm.set_start("foo")
    fsm.set_current("foo")

    event_thread = threading.Thread(target=monitor_events)
    event_thread.start()

    fsm_thread = threading.Thread(target=fsm.run)
    fsm_thread.start()

    event_thread.join()


if __name__ == "__main__":
    main()