def run(self):
        print 'Controller is waiting for window (HWND) to appear'
        self.hwnd = self.wait_and_get_firefox_hwnd_from_pid()
        print 'Controller got the HWND, and it is ' + str(self.hwnd)
        
        #just some shortcuts
        self.IAccessible = winutils.loadIAccessible()
        self.AccessibleObject = winutils.getAccessibleObjectFromWindow(hwnd = self.hwnd)
        
        print 'Accessible object is: ' + str(self.AccessibleObject)
        
        #starting listener
        self.listener = WindowsListener(hwnd = self.hwnd, pid = self.pid)
        self.listener.start()
        
        self._ready.set()
        
        print 'Listener is ready, call unpause_event_loop() to start pumping messages'
        
        # loop invariant: self._stateCondition is acquired, everywhere except wait() and sleep() lines
        self._stateCondition.acquire()
        while True:
            if self._stateActive:
                if self._statePaused == False:
                    self.listener.pump_messages() #TODO if function returns *always after all* messages are handled by WinProc, we can remove underlying lock to improve performance
                    messages = self.listener.get_queued_events()
                    self._process_messages(messages)
                    self._stateCondition.release()
                    sleep(1) #TODO here should be passive waiting
                    self._stateCondition.acquire()
                else:
                    self._stateCondition.wait()
                    continue
            else:

                break

        if self._statePaused == False:
            self.listener.stop()
        self._stateCondition.release()
class MatsMsaaController(MatsBaseController):
    
    def __init__(self, pid):
        MatsBaseController.__init__(self, pid)
        
        self._ready = Event()
        self._listeners = defaultdict(set) # event_id -> set(callables)
        
        #main loop controls:
        self._stateCondition = Condition()
        self._stateActive = True
        self._statePaused = True
        
    def run(self):
        print 'Controller is waiting for window (HWND) to appear'
        self.hwnd = self.wait_and_get_firefox_hwnd_from_pid()
        print 'Controller got the HWND, and it is ' + str(self.hwnd)
        
        #just some shortcuts
        self.IAccessible = winutils.loadIAccessible()
        self.AccessibleObject = winutils.getAccessibleObjectFromWindow(hwnd = self.hwnd)
        
        print 'Accessible object is: ' + str(self.AccessibleObject)
        
        #starting listener
        self.listener = WindowsListener(hwnd = self.hwnd, pid = self.pid)
        self.listener.start()
        
        self._ready.set()
        
        print 'Listener is ready, call unpause_event_loop() to start pumping messages'
        
        # loop invariant: self._stateCondition is acquired, everywhere except wait() and sleep() lines
        self._stateCondition.acquire()
        while True:
            if self._stateActive:
                if self._statePaused == False:
                    self.listener.pump_messages() #TODO if function returns *always after all* messages are handled by WinProc, we can remove underlying lock to improve performance
                    messages = self.listener.get_queued_events()
                    self._process_messages(messages)
                    self._stateCondition.release()
                    sleep(1) #TODO here should be passive waiting
                    self._stateCondition.acquire()
                else:
                    self._stateCondition.wait()
                    continue
            else:

                break

        if self._statePaused == False:
            self.listener.stop()
        self._stateCondition.release()

    def unpause_event_loop(self):
        '''
        starts event loop
        '''
        
        self._stateCondition.acquire()
        if self._statePaused:
            self.listener.start()
            self._statePaused = False
        self._stateCondition.notify()
        self._stateCondition.release()
        
    def pause_event_loop(self):
        '''
        pauses event loop, deregisters windows event hook method, cleans event queue
        '''
        
        self._stateCondition.acquire()
        if not self._statePaused:
            self.listener.stop()
            self.listener.pump_messages()
            self.listener.get_queued_events()
            self._statePaused = True
        self._stateCondition.notify()
        self._stateCondition.release()
        

    def stop(self):
        '''
        To be called by external thread. Stops Controller thread.
        '''
        self._stateCondition.acquire()
        self._stateActive = False
        self._stateCondition.notify()
        self._stateCondition.release()
        
        self.join()

        
    def register_event_listener(self, event_string, callable):
        with self._stateCondition:
            self._listeners[winconstants.eventNameToInt[event_string]].add(callable)
        
    def deregister_event_listener(self, event_string, callable):
        with self._stateCondition:#
            self._listeners[winconstants.eventNameToInt[event_string]].remove(callable)

    def _process_messages(self, messages):
        '''
        while here, stateConditionLock is acquired!
        '''
        for event in messages:
            for callable in self._listeners[event.get_id()]:
                callable(event)
            
    def clear_event_queue(self):
        with self._eventQueueLock:
            self._eventQueue = []
    
    def _inject_events(self, events):
        if len(events) > 0:
            with self._eventQueueLock:
                self._eventQueue.append(events)
    
    def wait_for_ready(self, timeout = None):
        self._ready.wait(timeout)
    
    def wait_and_get_firefox_hwnd_from_pid(self, timeout = 60):
        '''
        This method blocks controller thread until Firefox/Nightly window HWND is available.
        TODO : this method sucks, but I really need it in order for MATS to be
        reliable. Fix active waiting with something civilized. 
        '''
        
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(seconds=timeout):
            Nightlies = winutils.getNightliesByPID(self.pid)
            if len(Nightlies) > 0:
                break
            sleep(1)
        
        if len(Nightlies) == 0:
            raise Exception("Nightly window not found - HWND wait timeout")
        
        if len(Nightlies) > 1:
            print 'WARNING: more than one instance of Nightly found, using first one.'
            print Nightlies
        return Nightlies[0][0]
    
    def getAccessibleTree(self):
        return getAccessibleTreeFromMsaa(self.AccessibleObject)