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

# Copyright 2012-2013 Calculate Ltd. http://www.calculate-linux.org
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

from PySide import QtGui, QtCore
import time, urllib2
import dbus

from ReturnMessage import ReturnedMessage
from more import show_msg, get_sid

#class MySignal(QtCore.QObject):
#    sig = QtCore.Signal(str, str)

class TrayUpdateSystem(QtCore.QThread):
    mes_sig = QtCore.Signal(str, str)
    def __init__(self, target, parent = None):
        QtCore.QThread.__init__(self, parent)
        self._parent = target
    
    def run(self):
        self.close_flag = False
        if not hasattr(self._parent, 'localhost_ClientObj'):
            self.mes_sig.emit(_('Connection Error'), \
                           _('You are not connected to the localhost server'))
            return 1
        if not self._parent.localhost_ClientObj.client:
            self.mes_sig.emit(_('Connection Error'), \
                           _('You are not connected to the localhost server'))
            return 1

        sid = get_sid(self._parent.localhost_ClientObj.client)
        
        try:
            meth_result_temp = self._parent.localhost_ClientObj.client.service.\
                                                    system_update_tray(sid)
        except Exception, e:
            msg = e.message
            if type (e.message) == tuple:
                msg = ' '.join( map(lambda x:str(x), list(e.message)))

            self.mes_sig.emit(msg, 'cl-client-console Exception')
            return 1
        meth_result = []
        method_name = 'System update tray'
        error = False
        for res in meth_result_temp[0]:
            meth_result.append(ReturnedMessage(res.type, res.field, \
                                               res.message, res.expert))
            if res.type == 'error':
                error = True
            
        if error:
            return 1
        if meth_result[0].type == "pid":
            # create process dict
            self._parent.localhost_ClientObj.process_dict \
                                                [meth_result[0].message] = {}
            self._parent.localhost_ClientObj.process_dict \
                          [meth_result[0].message]['result'] = meth_result[0]
            self._parent.localhost_ClientObj.process_dict \
                               [meth_result[0].message]['name'] = method_name
            self._parent.localhost_ClientObj.process_dict \
                     [meth_result[0].message]['layout'] = QtGui.QVBoxLayout()
            self._parent.localhost_ClientObj.process_dict \
                            [meth_result[0].message]['layout'].setAlignment \
                            (QtCore.Qt.AlignTop)
        else:
            return 1
                    
        self.mes_sig.emit('', _('Update running'))
        
        mess = meth_result[0]
        pid = mess.message
        self._parent.sys_update_pid = int(pid)

        self.get_update_status(sid, pid)
                
    def get_update_status(self, sid, pid):
        end_frame = True

        try:
            current_frame = self._parent.localhost_ClientObj.client.\
                                        service.get_entire_frame(sid, pid)
        except urllib2.URLError:
            _print ('get_entire_frame in TrayIcon Exception')
            current_frame = None            
        while end_frame:
            while current_frame in [None, [], ""]:
                for i in range (5):
                    time.sleep(1.0)
                    if self.close_flag:
                        self.mes_sig.emit('', _('Update aborted'))
                        return 0
                try:
                    client = self._parent.localhost_ClientObj.client
                    current_frame = client.service.get_frame(sid, pid,"gui")
                except urllib2.URLError:
                    _print ('client.service.get_entire_frame in'
                            ' TrayIcon Exception')
                    current_frame = None
            for item in range(len(current_frame[0])):
                if current_frame[0][item].type == 'error':
                    self.mes_sig.emit(_("Failed to update!"), \
                                        current_frame[0][item].message)
                    end_frame = False
                    return 1
                elif current_frame[0][item].type == 'endTask':
                    if current_frame[0][item].message:
                        message = current_frame[0][item].message
                    else:  message = ''
                    self.mes_sig.emit(_('Update successfully completed'), \
                                            message)
                    end_frame = False
            current_frame = None

    def close(self):
        self.close_flag = True

class TrayIcon (QtGui.QSystemTrayIcon):
    def __init__(self, parent):
        super(TrayIcon, self).__init__(parent)
        self._parent = parent

        self.setIcon(QtGui.QIcon \
                        ('/usr/share/pixmaps/calculate-console-offline.png'))

        self.right_menu = RightButtonMenu(self, parent)
        self.left_menu = LeftButtonMenu(self, parent)

        self.activated.connect(self.activ)
        self.setToolTip('cl-console-gui - '+ _('System control'))
        self.setContextMenu(self.right_menu)

#        self.update_thread = TrayUpdateSystem(parent)
#        self.update_thread.mes_sig.connect(self.showMessage)

    def set_icon(self, online):
        if online:
            self.setIcon(QtGui.QIcon \
                        ('/usr/share/pixmaps/calculate-console-online.png'))
        else:
            self.setIcon(QtGui.QIcon \
                        ('/usr/share/pixmaps/calculate-console-offline.png'))

    def translate(self):
        # Translate left click menu
        self.left_menu.windowVisible.setText(_('Show/Hide Window'))
#        self.left_menu.sys_update.setText(_('Update system'))
        self.left_menu.exit_action.setText(_('Exit Program'))

        # Translate right click menu
        self.right_menu.about_action.setText(_('About'))
        self.right_menu.bug_action.setText(_("Report a Bug"))
        self.right_menu.tools_action.setText(_('Program settings'))
#        self.right_menu.sys_update.setText(_('Update system'))
        self.right_menu.exit_action.setText(_('Exit Program'))
        
    def help(self):
        self._parent.currentWidget().help()
        
    def bug_report(self):
        self._parent.currentWidget().bug_report()
    
    def tools(self):
        self._parent.currentWidget().tools()

    def exit(self):
#        if self.update_thread.isRunning():
#            text = _('The system is updated')
#            informative_text = _('Stop updating and exit?')
#            reply = show_question(self._parent, text, informative_text)
#
#            if reply == QtGui.QMessageBox.No:
#                return 0
#
#            elif reply == QtGui.QMessageBox.Yes:
#                self.update_thread.close()
#                self.update_thread.wait()
        self._parent._closeEvent()
    
    def activ(self, reason):
        if reason == QtGui.QSystemTrayIcon.MiddleClick:
            self.windowVisible()
        elif reason == QtGui.QSystemTrayIcon.Trigger:
            
            if QtGui.QCursor.pos().y() < self.left_menu.sizeHint().height():
                self.left_menu.move(QtCore.QPoint \
                           (self.geometry().x(), self.geometry().y()) + \
                           QtCore.QPoint(0, self.geometry().height() + 8))
            else:
                point = QtCore.QPoint(self.left_menu.sizeHint().width(), \
                                      self.left_menu.sizeHint().height() + 16)
                self.left_menu.move(QtGui.QCursor.pos() - point)
            self.left_menu.show()

    def showMessage(self, title, message, icon = 'dialog-warning'):

        # This uses the session bus because it's session-specific.
        bus = dbus.SessionBus()
        proxy = bus.get_object('org.freedesktop.Notifications', \
                               '/org/freedesktop/Notifications')
        interface = dbus.Interface(proxy,dbus_interface= \
                                            'org.freedesktop.Notifications')
        
        interface.Notify('cl-console-gui', 1, icon, title, message, [], {}, -1)

        ## KDE KNotify
        #bus = dbus.SessionBus()
        #knotify = bus.get_object('org.kde.knotify', '/Notify')
        #
        #knotify.event("warning", "kde", [], 'title', 'text', [], [], 0, 0,\
        #dbus_interface="org.kde.KNotify")

    def windowVisible(self):
        if self._parent.isVisible():
            self._parent.cur_pos = self._parent.pos()
            self._parent.hide()
        else:
            self._parent.show()
            self._parent.move(self._parent.cur_pos)

    def start_update_system(self):

        if not self.update_thread.isRunning():
            self.update_thread.start()
        else:
            show_msg(_('An update is already running'))

class LeftButtonMenu(QtGui.QMenu):
    def __init__(self, parent, MainWgt):
        QtGui.QMenu.__init__(self)
        # Add Show/Hide Window action
        themeName = QtGui.QIcon.themeName()
        window_icons = ['preferences-system-windows']
        window_icon = QtGui.QIcon()
        for image in window_icons:
            window_icon.setThemeName(themeName)
            window_icon = window_icon.fromTheme(image)
            if not window_icon.isNull():
                break
            window_icon.setThemeName('Tango')
            window_icon = window_icon.fromTheme(image)
            if not window_icon.isNull():
                break
        self.windowVisible = QtGui.QAction(window_icon, _("Show/Hide Window"),\
                                         self, triggered=parent.windowVisible)
        self.addAction(self.windowVisible)

#        # Add Update system action
#        update_icons = ['system-software-update']
#        update_icon = QtGui.QIcon()
#        for image in update_icons:
#            update_icon.setThemeName(themeName)
#            update_icon = update_icon.fromTheme(image)
#            if not update_icon.isNull():
#                break
#            update_icon.setThemeName('Tango')
#            update_icon = update_icon.fromTheme(image)
#            if not update_icon.isNull():
#                break
#
#        self.sys_update = QtGui.QAction(update_icon, _("Update system"), \
#                                 self, triggered=parent.start_update_system)
#        self.addAction(self.sys_update)
#
#        self.addSeparator()

        # Add exit action
        exit_icons = ['application-exit', 'system-log-out']
        exit_icon = QtGui.QIcon()
        for image in exit_icons:
            exit_icon.setThemeName(themeName)
            exit_icon = exit_icon.fromTheme(image)
            if not exit_icon.isNull():
                break
            exit_icon.setThemeName('Tango')
            exit_icon = exit_icon.fromTheme(image)
            if not exit_icon.isNull():
                break

        self.exit_action  = QtGui.QAction(exit_icon, _('Exit Program'), \
                                        self, triggered=parent.exit)

        self.addAction(self.exit_action)
#        self.setWindowOpacity(0.6)

#        bg_color_alpha = 'rgba(0,0,0,150)'
#        self.setStyleSheet( self.styleSheet() + \
#                    'QMenu {'\
#                    'color: white;'\
#                    'background-color: %s;' %bg_color_alpha +\
#                                       '}'\
#                    'QMenu::separator{background: %s;' %bg_color_alpha +\
#                    'width: 20px; height: 1px;}' \
#                    'QMenu::icon {background-color: transparent;'\
#                    'background: transparent}' \
#                     )

class RightButtonMenu(QtGui.QMenu):
    def __init__(self, parent, MainWgt):
        QtGui.QMenu.__init__(self)

        # Add about program
        About_icon = (QtGui.QIcon \
                        ('/usr/share/pixmaps/calculate-console-online.png'))
        themeName = QtGui.QIcon.themeName()
        if About_icon.isNull():
            about_icons = ['help-about','help-browser']
            About_icon = QtGui.QIcon()
            for image in about_icons:
                About_icon.setThemeName(themeName)
                About_icon = About_icon.fromTheme(image)
                if not About_icon.isNull():
                    break
                About_icon.setThemeName('Tango')
                About_icon = About_icon.fromTheme(image)
                if not About_icon.isNull():
                    break

        self.about_action  = QtGui.QAction(About_icon, _("About"),
                                           self, triggered=parent.help)
        self.addAction(self.about_action)

        # Add Bug report
        bug_icons = ['tools-report-bug','system-help','help-browser']
        bug_icon = QtGui.QIcon()
        for image in bug_icons:
            bug_icon.setThemeName(themeName)
            bug_icon = bug_icon.fromTheme(image)
            if not bug_icon.isNull():
                break
            bug_icon.setThemeName('Tango')
            bug_icon = bug_icon.fromTheme(image)
            if not bug_icon.isNull():
                break

        self.bug_action  = QtGui.QAction(bug_icon, _("Report a Bug"), self, \
                                                 triggered=parent.bug_report)
        self.addAction(self.bug_action)

        self.addSeparator()

        # Add tools
        tools_icons = ['preferences-other', 'preferences-system']
        tools_icon = QtGui.QIcon()
        for image in tools_icons:
            tools_icon.setThemeName(themeName)
            tools_icon = tools_icon.fromTheme(image)
            if not tools_icon.isNull():
                break
            tools_icon.setThemeName('Tango')
            tools_icon = tools_icon.fromTheme(image)
            if not tools_icon.isNull():
                break

        self.tools_action  = QtGui.QAction(tools_icon, _('Program settings'), \
                                        self, triggered=parent.tools)
        self.addAction(self.tools_action)

#        update_icons = ['system-software-update']
#        update_icon = QtGui.QIcon()
#        for image in update_icons:
#            update_icon.setThemeName(themeName)
#            update_icon = update_icon.fromTheme(image)
#            if not update_icon.isNull():
#                break
#            update_icon.setThemeName('Tango')
#            update_icon = update_icon.fromTheme(image)
#            if not update_icon.isNull():
#                break
#
#        self.sys_update  = QtGui.QAction(update_icon, _("Update system"), \
#                                  self, triggered=parent.start_update_system)
#        self.addAction(self.sys_update)

        self.addSeparator()
        exit_icons = ['application-exit', 'system-log-out']
        exit_icon = QtGui.QIcon()
        for image in exit_icons:
            exit_icon.setThemeName(themeName)
            exit_icon = exit_icon.fromTheme(image)
            if not exit_icon.isNull():
                break
            exit_icon.setThemeName('Tango')
            exit_icon = exit_icon.fromTheme(image)
            if not exit_icon.isNull():
                break

        self.exit_action  = QtGui.QAction(exit_icon, _("Exit Program"), \
                                        self, triggered=parent.exit)
        self.addAction(self.exit_action)
