#!/usr/bin/python

__doc__ = """
usage: 
  tango_monitor <device name> [ <attr regexp> ]*
"""

import sys
import time
import PyTango
import fandango as fn

class MyCallback(object):
    
    counter = 0
    
    def __init__(self):
        self.t0 = time.time()
        self.counters = fn.dicts.defaultdict(int)
        self.values = fn.dicts.defaultdict(str)
        self.dups = fn.dicts.defaultdict(int)
        self.ratios = fn.dicts.defaultdict(float)

    def push_event(self,event):

        MyCallback.counter+=1
        aname = fn.tango.get_normal_name(event.attr_name)
        self.counters[aname] = self.counters[aname] + 1
        self.ratios[aname] = self.counters[aname] / (time.time()-self.t0)
        
        value = fn.shortstr(event.attr_value and event.attr_value.value)
        if self.values[aname] == value:
            self.dups[aname] += 1
            
        self.values[aname] = value
        print('%s:%s = %s; ct=%d/%d, e/s=%2.2f, dups=%d' %
                (fn.time2str(),aname,value,self.counters[aname],
                MyCallback.counter,self.ratios[aname],self.dups[aname]))
        

def monitor(d, args=[], events = []):
  """
  monitor(device,[attributes])
  """
    
  dp = PyTango.DeviceProxy(d)
  cb = MyCallback() #PyTango.utils.EventCallBack()

  args = map(str.strip, args) if args else ["state"]
  attrs = [a for a in dp.get_attribute_list()
           if any(fn.clmatch(r,a) for r in args)]
  events = events or [PyTango.EventType.CHANGE_EVENT]
    
  print('%s matched %d attributes' % (d,len(attrs)))

  eis,worked,failed = [],[],[]
  for a in attrs:
    try:
      for e in events:
        eis.append(dp.subscribe_event(a,e,cb))
      worked.append(a)
    except:
      #print(fn.except2str())
      failed.append(a)

  print('%d attributes NOT provide events: %s' % (len(failed),failed))      
  print('%d attributes provide events: %s' % (len(worked),worked))
  print('-'*80 + '\n' + '-'*80)
  try:
      while True:
          time.sleep(1)
  except: #KeyboardInterrupt
      print(fn.except2str())
      print('-'*80)
      print "Finished monitoring"
      
  [dp.unsubscribe_event(ei) for ei in eis];
    
if __name__ == '__main__':
  import sys
  try:
    monitor(sys.argv[1],sys.argv[2:])
  except:
    print(fn.except2str())
    print(__doc__)
    

