# -*- coding: utf-8 -*-

#   This file is part of emesene.
#
#    Emesene 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.
#
#    emesene 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 emesene; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import os
import gtk
import gobject

disabled = False
type_ = 'gtk'

if not gtk.check_version( 2, 10, 0 ) == None:
    if os.name == 'posix':
        try:
            import egg.trayicon
            type_ = 'egg'
        except:
            print 'No tray icon library detected'
            disabled = True
    elif os.name == 'nt':
        try:
            from gtkwin32 import *
            WM_LBUTTONUP = 0x0202
            WM_RBUTTONUP = 0x0205
            type_ = 'win'
        except:
            print 'No tray icon library detected'
            disabled = True

# WARNING: disable for release until stable enough.
#try:
#    import appindicator
#    type_ = 'indicator'
#    disabled = False
#except:
#    pass

class TrayIcon:
    '''This class creates the tray icon notification - Pre-GTK 2.10'''

    def __init__(self, controller):
        '''Constructor'''
        global disabled
        
        self.controller = controller
        self.config = self.controller.config
        self.mainWindow = self.controller.mainWindow
        self.theme = self.controller.theme
        self.status = ''
        self.tray = None
        self.ind = None

        disabled = self.config.glob['disableTrayIcon']

        try:
            if disabled:
                pass
            elif type_ == 'gtk':
                self.tray = gtk.StatusIcon()
                self.tray.set_tooltip( 'emesene' )
                pixbuf = self.theme.getImage('trayicon')
                self.tray.set_from_pixbuf( pixbuf )
                self.buildMenu()
                self.tray.hide = lambda: self.tray.set_visible( False )
                self.tray.show = lambda: self.tray.set_visible( True )
                
                self.tray.connect( 'activate', self.on_activate )
                self.tray.connect( 'popup-menu', self.on_popup_menu )
            elif type_ == 'indicator':
                self.ind = appindicator.Indicator("emesene", \
                        "trayicon", appindicator.CATEGORY_APPLICATION_STATUS, \
                        self.theme.path)
                print self.ind.get_property("icon-theme-path")
                self.ind.set_status(appindicator.STATUS_ACTIVE)
                self.ind.set_attention_icon("lunch")
                self.buildMenu()
                self.ind.set_menu(self.menu)
            elif os.name == 'posix':
                self.tray = egg.trayicon.TrayIcon('emesene')
                self.buildTrayIconPosix()
                self.buildMenu()
            elif os.name == 'nt':
                # Note: gtk window must be realized before installing extensions.
                self.mainWindow.realize()
                self.win32ext = GTKWin32Ext(self.mainWindow)
                self.buildMenu()
                self.buildTrayIconWin32()
        except Exception, e:
            print 'exception creating trayicon: ' + str( e )
            disabled = True
            
    def remove(self):
        '''remove the trayicon'''

        if os.name == 'nt' and type_ != 'gtk': 
            self.win32ext.remove_notify_icon()
        elif type_ == 'indicator':
            self.ind.set_status(appindicator.STATUS_PASSIVE)
        else:
            self.tray.hide()
        
    def buildTrayIconPosix(self):
        '''Build the trayIcon for linux'''

        self.eventBox = gtk.EventBox()
        pixbuf = self.theme.getImage('trayicon')
        self.image = gtk.Image()
        self.image.set_from_pixbuf( pixbuf )

        self.eventBox.set_events(gtk.gdk.BUTTON_PRESS_MASK)
        self.eventBox.connect_object('button_press_event', self.iconClickPosix, self.eventBox)

        self.tooltips = gtk.Tooltips()
        self.tooltips.set_tip(self.eventBox, 'emesene')
        
        self.eventBox.add(self.image)
        self.tray.add(self.eventBox)
        self.eventBox.show_all()
        self.tray.show_all()

    def update(self, newUserStatus, pixbuf=None):
        
        self.status = newUserStatus

        if type_ == 'gtk':
            func = self.tray.set_from_pixbuf
        elif type_ == 'egg':
            func = self.image.set_from_pixbuf
        elif type_ == 'indicator':
            self.ind.set_icon(self.theme.statusToPixbuf(newUserStatus, False))
            self.ind.set_menu(self.menu)
            self.menu.show_all()
            return

        if pixbuf == None:
            func(self.theme.statusToPixbuf(newUserStatus))
        else:
            func(pixbuf)

        if self.controller.msn and self.controller.userEmail:
            text = 'emesene - ' + str(self.controller.userEmail)
            if type_ == 'egg':
                self.tooltips.set_tip(self.eventBox, text)
            elif type_ == 'gtk':
                self.tray.set_tooltip(text)
        
    def buildTrayIconWin32(self):
        '''Build the trayIcon for windows'''

        ## http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/icons/iconreference/iconfunctions/loadicon.asp
        hicon = win32gui.ExtractIcon(0, 'themes\\' + \
            self.config.user['theme'] + '\\' + 'trayicon.ico', 0)
        self.win32ext.add_notify_icon(hicon, 'Emesene') # TODO: account
        self.win32ext.notify_icon.menu = self.menu

        # Set up the callback messages
        self.win32ext.message_map({WM_TRAYMESSAGE: self.iconClickWin32})

    def iconClickWin32(self, hwnd, message, wparam, lparam):
        '''the event handler for windows'''

        if lparam == WM_RBUTTONUP:
            self.win32ext.notify_icon.menu.popup(None, None, None, 0, 0)
        elif lparam == WM_LBUTTONUP:
            self.win32ext.notify_icon.menu.popdown()
            self.showHide()

    def iconClickPosix(self, widget, event):
        '''the event handler for linux'''

        if event.type == gtk.gdk.BUTTON_PRESS: # Single click
            if event.button == 1: # Left Click
                self.showHide(self.eventBox)
            elif event.button == 3: # Right Click - Show popup
                self.menu.popup(None, None, None, event.button, event.time)
                
    def on_popup_menu( self, status_icon, button, activate_time ):
        position = gtk.status_icon_position_menu
        if os.name == 'nt':
            position = None       
        self.menu.popup( None, None, position, button, activate_time, status_icon )

    def on_activate( self, status_icon ):
        if self.tray.get_blinking():
            conv = self.controller.conversationManager.newest_message_conv
            conv_window = conv.parentConversationWindow

            if conv_window.get_urgency_hint():
                if conv_window.tabs.get_show_tabs():
                    conv_window.showTab(conv_window.tabs.page_num(conv.ui))
            conv_window.present()
        else:
            self.showHide()

    def buildMenu(self):
        '''Build the menu widget'''

        self.menu = gtk.Menu()
        
        menuItemQuit = gtk.ImageMenuItem( gtk.STOCK_QUIT )
        menuItemQuit.connect('activate', self.on_quit)

        menuItemShowHide = gtk.MenuItem(_("Hide/Show emesene"))
        menuItemShowHide.connect('activate', self.showHide)

        self.menu.append(menuItemShowHide)
        self.menu.append(menuItemQuit)
        if os.name == "nt":
            self.timerID = None
            self.menu.connect("leave-notify-event", self.start_timer_nt)
        self.menu.show_all()

    #I had to add all this "timerID != None" checks because the "source_remove"
    #method doesn't stop the timeout_add function, am I doing something grown? -arielj
    def start_timer_nt(self, menu, event):
        if self.timerID == None:
            self.timerID = gobject.timeout_add_seconds(2, self.popdownmenu )
        self.deleteTimerID = self.menu.connect("motion-notify-event", self.remove_timer)

    def remove_timer(self, menu, event):
        if self.timerID != None:
            gobject.source_remove(self.timerID)
            self.timerID = None

    def popdownmenu(self):
        if self.timerID != None:
            self.menu.popdown()
        return False
        
    def on_quit( self, menuitem):
        self.controller.quit( 0 )
    
    def showHide(self, widget = None):
        '''Show or hide the main window'''

        if self.mainWindow.flags() & gtk.VISIBLE:
            self.mainWindow.hide()
        else:
            self.mainWindow.deiconify()
            self.mainWindow.show()
            
    def getNotifyObject( self ):
        if not disabled and not type_ == 'gtk' and not type_ == 'indicator':
            return self.tray
        return None

