#!/usr/bin/python2
# -*- coding: utf-8 -*-

# ibamtray by Derek Tucker 2009 <derek at tetonedge dot net>
# based off of vubat.py by simon ortling 2008 <krabat at vonuebel dot com>
# version 0.02

"""
ibamtray is an ibam systray frontend.
Copyright (C) 2009 Derek Tucker (aka tetonedge)
Original Code is from vubat by Simon Ortling:
Copyright (C) 2008 Simon Ortling (aka Krabat vonUebel)

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 3 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 thisprogram.
If not, see <http://www.gnu.org/licenses/>.
"""

import sys, os
import re

# gtk modules
import pygtk
pygtk.require ('2.0')
import gtk, gobject
import pynotify

CHECK_INTERVAL = 2000 # in milliseconds
SAMPLE_INTERVAL = 60 # in check turns

IBAM_RO_CMD = "ibam -sr --percentbattery"
IBAM_RW_CMD = "ibam -s --percentbattery"
IBAM_SEARCH_PTRN = re.compile ("(^[\w|\s]+?:\s*)([\d|:]*)")

def get_pixmap_dir ():
    """search for status icons"""
    for item in ("/usr/share/pixmaps/ibamtray",
        "/usr/local/share/pixmaps/ibamtray",
        "./pixmaps"):
        if os.access (item, os.R_OK):
            return item
PIXMAP_DIR = get_pixmap_dir ()

class IBAMInfo:
    def __init__ (self):
        self.status = 0
        self.percentage = 0
        self.battery_time = 0
        self.adapted_time = 0
        self.check_count = SAMPLE_INTERVAL
	pynotify.init("IBAM Tray Icon")

    def check (self):
        self.check_count += 1
        if self.check_count >= SAMPLE_INTERVAL:
            # check and write sample
            self.check_count = 0
            data = os.popen (IBAM_RW_CMD).read ().strip ().split ("\n")
        else:
            # check read only
            data = os.popen (IBAM_RO_CMD).read ().strip ().split ("\n")
        self.percentage, self.battery_time, self.adapted_time = [
            int (re.search (IBAM_SEARCH_PTRN, x).group (2)) for x in data]
        if data [1].startswith ("Battery"):
            self.status = 0
        elif data [1].startswith ("Charge"):
            self.status = 1
        else:
            self.status = 2        

class Application:
    def __init__ (self):
        self.info = IBAMInfo ()
        self.icon = gtk.StatusIcon ()
        #self.icon.connect ("activate", self.on_activate)
        self.icon.connect ("popup_menu", self.on_popup_menu)
        self.icon.set_visible (True)
        self.status_labels = ("Battery", "Charging", "Charged")
        self.last_pixmap = None
        self.notifystatus = 0
        self.stat = "None"

    def run (self):
        self.update_status ()
        gtk.main()

    def get_pixmap (self):
        idx = 5
        tmp = 0
        for i in range (5):
            tmp += (i+1)*10
            if self.info.percentage <= tmp:
                idx = i+1
                break
        self.notifystatus = idx
        self.stat = self.status_labels [self.info.status]
        if self.info.percentage == 100:
            idx = 5
        return "status%d%s.svg"%(idx,self.stat), self.notifystatus,self.stat

    def update_status (self):
        self.info.check ()
           
        pixmap,notifystatus,stat = self.get_pixmap ()
        if self.last_pixmap != pixmap:
            self.icon.set_from_file (os.path.join (PIXMAP_DIR, pixmap))
            self.last_pixmap = pixmap
            
            if notifystatus == 1:
                n = pynotify.Notification("Battery Critical", "Battery less than 5%, Please Charge")
                p = gtk.gdk.pixbuf_new_from_file((os.path.join (PIXMAP_DIR, "status1Battery.svg")))
                n.set_icon_from_pixbuf(p)
                n.set_urgency(pynotify.URGENCY_CRITICAL) 
                n.set_timeout(pynotify.EXPIRES_NEVER)
                n.show()
            
            if stat == "Battery":
                n = pynotify.Notification("Battery Discharging", "A/C is Disconnected")
                p = gtk.gdk.pixbuf_new_from_file((os.path.join (PIXMAP_DIR, "status5Battery.svg")))
                n.set_icon_from_pixbuf(p)
                n.show()
            
            if stat == "Charging":
                n = pynotify.Notification("Battery Charging", "A/C is Connected")
                p = gtk.gdk.pixbuf_new_from_file((os.path.join (PIXMAP_DIR, "charging.svg")))
                n.set_icon_from_pixbuf(p)
                n.show()

            if stat == "Charged":
                n = pynotify.Notification("Battery Charged", "Charge is 100%")
                p = gtk.gdk.pixbuf_new_from_file((os.path.join (PIXMAP_DIR, "charger.svg")))
                n.set_icon_from_pixbuf(p) 
                n.show()

        self.icon.set_tooltip ("%s\n%d%%\n%d:%02d"%(
            self.status_labels [self.info.status],
            self.info.percentage, 
            self.info.adapted_time/3600,
            (self.info.adapted_time/60)%60))

        gobject.timeout_add (5000, self.update_status)

    def on_activate_response (self, widget, response, data= None):
        widget.hide ()

    def on_activate (self, button, widget, data=None):
        pass

    def on_popup_response (self, widget, response, data= None):
        if response == gtk.RESPONSE_OK:
            gtk.main_quit ()
        else:
            widget.hide ()

    def on_popup_menu (self, button, widget, data=None):
        dialog = gtk.MessageDialog (parent=None, 
            flags=gtk.DIALOG_DESTROY_WITH_PARENT,
            type=gtk.MESSAGE_INFO,
            buttons=gtk.BUTTONS_OK_CANCEL,
            message_format="Quit?")
        dialog.set_title ("Quit ibam tray?")
        dialog.connect ("response", self.on_popup_response)
        dialog.show ()


if __name__ == "__main__":
    app = Application ()
    app.run ()
