################ 待整理 

from cppy.cp_util import *
'''
订阅者 = 注册者 = 观察者

注册回调的一个变体
要点是：中心化、统一化

为了简化消息订阅可能形成的复杂性，
提供一个中心消息管理器统一负责消息的订阅和回调
各个功能组件只是完成自己的功能，
在中心管理器上订阅消息挂到自己响应的处理函数上

总结，相比较的改变：
- 注册的时候，通过提供一个类型字段标识不同消息
- 其它实体不做注册和做回调，统一这两个功能到一个中心单元

这是一个示例性质的原型，具体分布式环境下需要调整
'''
from collections import defaultdict
#################################################
# Event Manager
#################################################
class EventManager:
    def __init__(self):
        self._subs = defaultdict(list)

    def subscribe(self, event_type, handler):
        self._subs[event_type].append(handler)

    def publish(self, event):
        event_type = event[0]        
        for handle in self._subs.get(event_type, []):  
            handle(event)

#################################################
# Application Entities
#################################################
class DataStorage:    
    def __init__(self, event_manager):
        self._event_manager = event_manager
        self._event_manager.subscribe('load', self._load)
        self._event_manager.subscribe('start', self.produce_words)

    def _load(self, event):        
        self._data = extract_file_words( event[1] )

    def produce_words(self, _):        
        for word  in self._data:
            self._event_manager.publish(('word', word ))
        self._event_manager.publish(('eof', None))

class StopWordFilter:    
    def __init__(self, event_manager):        
        self._event_manager = event_manager
        self._event_manager.subscribe('load', self.load_stop_words)
        self._event_manager.subscribe('word', self.filter_word)
        self._stop_words = set()

    def load_stop_words(self, _ ):        
        self._stop_words = set( get_stopwords() )

    def filter_word(self, event):
        word = event[1]
        if word not in self._stop_words:
            self._event_manager.publish(('valid_word', word))

class WordFrequencyCounter:    
    def __init__(self, event_manager):        
        self._event_manager = event_manager
        self._event_manager.subscribe('valid_word', self.count_word)
        self._event_manager.subscribe('print', self.print_freqs)
        self._word_freqs = {}

    def count_word(self, event):
        word = event[1]
        self._word_freqs[word] = self._word_freqs.get(word, 0) + 1        

    def print_freqs(self, _ ):
        print_word_freqs ( sort_dict (self._word_freqs) )      
      
class WordFrequencyApp:
    def __init__(self, event_manager):
        self._event_manager = event_manager
        self._event_manager.subscribe('run', self.start_application)
        self._event_manager.subscribe('eof', self.stop_application)

    def start_application(self, event):
        path_to_file = event[1]
        self._event_manager.publish(('load', path_to_file))
        self._event_manager.publish(('start', ))

    def stop_application(self, _ ):
        self._event_manager.publish(('print', ))


def main():    
    event_manager  = EventManager()
    DataStorage( event_manager )
    StopWordFilter( event_manager )
    WordFrequencyCounter( event_manager )
    WordFrequencyApp( event_manager )
    event_manager.publish(('run', testfilepath ))

if __name__ == "__main__":
    main()    