#!/usr/bin/env python

import sys
import gtk
import appindicator

import imaplib
import re

import os
import pynotify

PING_FREQUENCY = 10 # seconds

def exec_command(command):
  stream = os.popen(command)
  out = stream.read()
  out = re.split('\n',out);
  res = []
  for newline in out:
    if len(newline)==0:
      continue;
    elif newline.startswith("Error:"):
      res=[];
      break;
    else:
      res.append(newline)
  return res

class CheckNUT:

    def __init__(self):
        self.ind = appindicator.Indicator("nut-indicator",
                                          "gpm-ups-100-charging",                                        
	                                  appindicator.CATEGORY_APPLICATION_STATUS)
        self.ind.set_status(appindicator.STATUS_ACTIVE)
        self.ind.set_attention_icon("gpm-ups-000")

	hosts = sys.argv[1:]

	if len(hosts)==0:
          hosts = {'localhost'}

        self.upses=[]
        for host in hosts : 
          command = "upsc -l {0}".format(host)
          try:
            local_upses=exec_command(command)
            for ups in local_upses:
              self.upses.append('{0}@{1}'.format(ups,host))
          except:
            pass

        if self.upses == []:
          print "No connected ups'es found!\n"
          sys.exit(1)
          
        self.menu_setup()
        self.ind.set_menu(self.menu)

        if not pynotify.init ("nut-indicator"):
          self.disable_notify=1
        else:
          self.disable_notify=0

        self.ups_dictionary = {}
        self.ups_dictionary['battery charge'] = 'Battery charge %'
        self.ups_dictionary['input voltage'] = 'Input voltage'
        self.ups_dictionary['output voltage'] = 'Output voltage'
        self.ups_dictionary['ups load'] = 'UPS load %'
        self.ups_dictionary['ups status'] = 'UPS status'

        self.ups_value_dictionary = {}
        self.ups_value_dictionary['ups status'] = {}
        self.ups_value_dictionary['ups status']['OL'] = {1,'online'}
        self.ups_value_dictionary['ups status']['OB'] = {0,'on battery'}
        self.ups_value_dictionary['ups status']['LB'] = {-1,'low batter'}

    def menu_setup(self):
        self.menu = gtk.Menu()

        self.menuitems = {}
        for ups in self.upses:
          print ups;
          menu_item = gtk.MenuItem(ups)
          menu_item.connect("activate",self.call_check_local_ups,ups)
          menu_item.show()
          self.menu.append(menu_item)
          self.menuitems[ups]=menu_item

        separator = gtk.SeparatorMenuItem()
        separator.show()
        self.menu.append(separator)

        self.quit_item = gtk.MenuItem("Quit")
        self.quit_item.connect("activate", self.quit)
        self.quit_item.show()
        self.menu.append(self.quit_item)

    def main(self):
        self.check_ups()
        gtk.timeout_add(PING_FREQUENCY * 1000, self.check_ups)
        gtk.main()

    def quit(self, widget):
        sys.exit(0)

    def call_check_local_ups(self,item,ups):
        return self.check_local_ups(ups,1)

    def check_local_ups(self,ups,notify):
        command = "upsc {0}".format(ups)
        res = exec_command(command)
        status="?"
        battery="?"
        ups_status="?"
        text=""
        minstatus=1
        for newline in res:
          paramname,paramvalue = newline.split(': ',1)
          paramname = paramname.replace('.',' ')
          try:
            status,paramvalue = self.ups_value_dictionary[paramname][paramvalue]
            if status<minstatus:
              status=minstatus
          except:
            pass
          try:
            printname = self.ups_dictionary[paramname]
            text="{0}\n{1} = {2}".format(text,printname,paramvalue)
          except:
            pass
            
          if paramname=="battery charge":
            battery=paramvalue
          elif paramname=="ups status":
            ups_status=paramvalue

        if battery=='?':
          self.menuitems[ups].get_child().set_text('{0}: {1}'.format(ups,ups_status))
        else:
          self.menuitems[ups].get_child().set_text('{0}: {1}, {2}%'.format(ups,ups_status,battery))
        if (notify==1 or minstatus<0) and self.disable_notify==0:
          n = pynotify.Notification(ups,text)
          helper = gtk.Button()
          icon = helper.render_icon(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_DIALOG)
          n.set_icon_from_pixbuf(icon)
          n.show()
        return minstatus

    def check_ups(self):

        min_status=1;

        for ups in self.upses:
          status=self.check_local_ups(ups,0)
          if status<min_status:
            min_status=status

        if status < 0:
            self.ind.set_status(appindicator.STATUS_ATTENTION)
            self.ind.set_attention_icon("gpm-ups-000")
        elif status==0:
            self.ind.set_status(appindicator.STATUS_ATTENTION)
            self.ind.set_attention_icon("gpm-ups-060")
        else:
            self.ind.set_status(appindicator.STATUS_ACTIVE)
        return True

if __name__ == "__main__":
    indicator = CheckNUT()
    indicator.main()

