# Copyright (c) 2001 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307
# USA.
__revision__ = "$Id: HornEventDispatcher.py,v 1.5 2002/01/03 17:29:21 syt Exp $"

class HornEventDispatcher:
    _DICT = {}
    def __init__(self):
        self.__dict__ = HornEventDispatcher._DICT
        if not self.__dict__:
            # use a queue to execute functions
            import Queue
            self.queue = Queue.Queue(0)
            # list of listeners
            self.listeners = {'plan':[], 'memory':[], 'engine':[]}
        
    def process_queue(self):
        import Queue
        try:
            event = self.queue.get_nowait()
            for object in self.listeners[event[0]]:
                apply(getattr(object,event[1]),event[2])
        except Queue.Empty :
            pass
        except:
            print 'Error while prcessing queue'
            import traceback
            traceback.print_exc()
        return 1
    
    def add_listener(self, type, instance):
        assert type in ('plan', 'memory', 'engine')
        self.listeners[type].append(instance)

    def remove_listener(self, type, instance):
        assert type in ('plan', 'memory', 'engine')
        # since we use borg pattern, this stuff is necessary to remove listeners
        for l in self.listeners[type]:
            if l.__dict__ is instance.__dict__:
                self.listeners[type].remove(l)
                
    ## memory listener interface ##################################"
    def addElement(self,elementXml):
        print '(addElement) add in queue', elementXml
        self.queue.put(('memory', 'addElement', (elementXml,)))
    def removeElement(self,elementId):
        print '(removeElement) add in queue', elementId
        self.queue.put(('memory', 'removeElement', (elementId,)))
    def startPlan(self,recipeName):
        self.queue.put(('memory', 'startElement', (recipeName,)))
    def replaceElement(self, elementId):
        self.queue.put(('memory', 'replaceElement', (elementId,)))
    def getMemory(self):
        self.queue.put(('memory', 'getMemory', ()))
    def getElement(self,elementId):
        self.queue.put(('memory', 'getElement', (elementXml,)))
    def getElementsList(self):
        self.queue.put(('memory', 'getElementsList', ()))
    def getElementList(self,elementId):
        self.queue.put(('memory', 'getElementList', (elementId,)))
    # engine listener interface #################################
    def postQueueEvent(self,evtId,text) :
        self.queue.put(('engine', 'postQueueEvent', (evtId, text)))
    def popQueueEvent(self,evtId) :
        self.queue.put(('engine', 'popQueueEvent', (evtId,)))
    def postSchedulerEvent(self,evtId,text) :
        self.queue.put(('engine', 'postSchedulerEvent', (evtId, text)))
    def popSchedulerEvent(self,evtId) :
        self.queue.put(('engine', 'popSchedulerEvent', (evtId)))
    # plan listener interface #################################
    def fireTransition(self,planId,transitionId):
        self.queue.put(('plan', 'fireTransition', (planId, transitionId)))
    def transitionStatusChanged(self,planId,transitionId, status):
        self.queue.put(('plan', 'transitionStatusChanged',
                        (planId, transitionId, status)))
    def stepStatusChanged(self,planId,stepId,status):
        self.queue.put(('plan', 'stepStatusChanged', (planId, stepId, status)))
    def planStatusChanged(self,planId,status):
        self.queue.put(('plan', 'planStatusChanged', (planId, status)))
    def instanciateRecipe(self,planId,recipeName):
        self.queue.put(('plan', 'instanciateRecipe', (planId, recipeName)))
    def planAddElement(self,planId,elementId):
        self.queue.put(('plan', 'planAddElement', (planId, elementId)))
    def planRemoveElement(self,planId,elementId):
        self.queue.put(('plan', 'planRemoveElement', (planId, elementId)))

