#!/usr/bin/python2.5
#

__author__    = "Eero af Heurlin <eero.afheurlin@iki.fi>"
__version__   = "0.1.0"
__date__      = "2007-02-11"
__copyright__ = "Copyright (c) 2007 %s. All rights reserved." % __author__
__licence__   = "GPL"

import dbus
import osso
import gtk, gobject
from maemoplazer import MaemoPlazer
import sys

from SimpleGladeApp import SimpleGladeApp
from SimpleGladeApp import bindtextdomain
import hildon
import os

app_name = "MaemoPlazer"
app_version = "0.1.1"
app_authors = [
                'Eero af Heurlin <eero.afheurlin@iki.fi>',
                'Henri Bergius <bergie@iki.fi>'
              ]
app_copyright = 'Copyright (c) 2007-2008 Midgard community'
app_website = 'https://garage.maemo.org/projects/maemoplazer/'

glade_dir = '../share/maemoplazer'
locale_dir = ''
KEEP_ALIVE_TIME = 1000*60*9 # 9 minutes (Plazes session timeut is 10...)

class maemoplazer_ui(SimpleGladeApp, MaemoPlazer):
#    def __init__(self, path="maemoplazer.glade", root="maemoplazer_main", domain=app_name, **kwargs):
    def __init__(self, path="maemoplazer.glade", root=None, domain=app_name, **kwargs):
        # initialize properties
        self.osso_c = False
        self.current_location = ''
        self.current_session = False
        self.retry_count = 0
        
        # Initialize Glade
        path = os.path.join(glade_dir, path)
        SimpleGladeApp.__init__(self, path, root, domain, **kwargs)

    def new(self):
        # "real" init

        #for widget in self.get_widgets():
        #    widget_name = gtk.Widget.get_name(widget)
        #    print widget_name

        dialog = self.get_widget('passwd_dialog')
        dialog.hide()

        # Hildonize
        self.app = hildon.Program()
        self.window = hildon.Window()
        self.window.connect('destroy', self.on_maemoplazer_main_destroy)
        ## menu
        menu = gtk.Menu()
        for child in self.menu_mainmenu.get_children():
            child.reparent(menu)
        self.window.set_menu(menu)
        self.menu_mainmenu.destroy() 
        ## window
        self.app.add_window(self.window)
        self.maincontainer.reparent(self.window)
        self.maemoplazer_main.connect('destroy', self.dummy_destroy)
        self.maemoplazer_main.destroy()

        self.window.show_all()
        self.window.set_title('MaemoPlazer')
        self.label_plazeinfo.set_text(_('No Plazes information available'))

        # Initialize OSSO context (which clears the loading icon) now that we have glade etc up
        self.osso_c = osso.Context("maemoplazer_ui", "0.0.1", False)
        # Initialize lower level classes
        self.init_maemoplazer()

        # Initialize logger
        self.logger_initialize()

        # Register network status listener
        self.icd_listener_initialize()

        # All done
        self.log(_('Initialized'))
        # Plaze us once (give 1.5 seconds for stuff to come up properly)
        gobject.timeout_add(1500, self.relogin_timeout)

    def updateAccount(self):
        dialog = self.get_widget('passwd_dialog')
        response = dialog.run()
        dialog.hide()
        if response == gtk.RESPONSE_OK:
            self.saveUserPass(self.username.get_text(), self.password.get_text())
            return True
        else:
            return False

    def init_maemoplazer(self):
        configfile = os.path.expanduser('~/.maemoplazes.cfg')
        MaemoPlazer.__init__(self, configfile, self.osso_c)

    def icd_listener_initialize(self):
        # Attach to Internte Connection Daemon status signals
        bus = dbus.SystemBus()
        bus.add_signal_receiver(self.icd_status_changed, 'status_changed', 'com.nokia.icd', 'com.nokia.icd', '/com/nokia/icd')
        # We seem to need this to make the receiver work correctly
        self.log(_('ICD Listener attached'))

    def icd_status_changed(self, interface, method, arguments, user_data):
        #self.log("DEBUG: icd_status_changed called")
        #self.log("  interface: %s" % interface)
        #self.log("  method: %s" % method)
        #self.log("  arguments: %s" % arguments)
        #self.log("  user_data: %s" % user_data)
        # Call logoff if arguments is 'DISCONNECTING'
        if (arguments == 'DISCONNECTING'):
            try:
                gobject.timeout_add(1, self.log_out_timeout)
            except:
                # We might not have network here (which will cause exceptions from XML-RPC layer to bubble up
                pass
            return
        # Only plaze us if this is a new WLAN connection
        if (   method != 'WLAN_INFRA'
            or arguments != 'CONNECTED'):
            return
        try:
            self.log('Detected WLAN via ICD')
            # Plaze us (after 0.1 seconds of waiting for things to finish)
            gobject.timeout_add(100, self.get_show_current_plaze_timeout)
        except:
            # DBUS traps exceptions during callbacks and prints very little of them
            self.log("WARN: Got exception, trying to print traceback")
            import traceback, sys
            stack_f = traceback.format_list(traceback.extract_tb(sys.exc_traceback))
            for line in stack_f:
                self.log(line.trim())
            self.log("Traceback printed (i hope)")

        return

    def uiMessage(self, message):
        self.log('UIMESSAGE: ' + message)
        MaemoPlazer.uiMessage(self, message)

    def get_show_current_plaze_timeout(self):
        #self.log('get_show_current_plaze_timeout called')
        self.get_show_current_plaze()
        return False

    def keep_alive(self):
        self.log('keep_alive called')
        if (self.current_session == False):
            return False
        try:
            status = self.update(self.current_session, self.current_location)
        except:
            status = False
        # Critical failure
        if (status == False):
            return False
        return True

    def relogin_timeout(self):
        #self.log('relogin_timeout called')
        self.relogin()
        return False

    def relogin(self):
        # Restarts session and plazes us
        self.retry_count = self.retry_count + 1
        if (self.retry_count > 5):
            self.log("relogin retry count exceeded")
            self.retry_count = 0
            return True
        if (self.plazed):
            self.log_out()
        self.current_location = False
        self.current_session = False
        try:
            self.current_location = self.getLocationID()
            if (self.current_location == None):
                # Failure in resolving location ID, recurse in 3 sec.
                self.log("Could not resolve location ID, trying again")
                gobject.timeout_add(1500, self.relogin_timeout)
                #self.log("Could not resolve location ID, try again")
                self.current_location = False
                self.label_plazeinfo.set_text(_('No Plazes information available'))
                return False
            #self.log("Got location ID %s" % self.current_location)
        except:
            self.label_plazeinfo.set_text(_('No Plazes information available'))
            self.current_location = False
            return False
        self.retry_count = 0
        self.current_session = self.login(self.current_location)
        if (self.current_session == False):
            return False
        return self.plaze_nice()

    def plaze_nice(self):
        if (self.current_session == False):
            return self.relogin()
        status = self.update(self.current_session, self.current_location)
        # Critical failure
        if (status == False):
            return False
        if (status['update'] == 2):
            # New plaze
            self.plaze_url = str(status['editurl'])
            return self.open_current_plaze()
        info = self.plazeinfo(self.current_session, self.current_location)
        if (info == False):
            return False
        self.log("Plazed to %s" % self.convert(str(self.plaze['name'])))
        self.label_plazeinfo.set_text(self.convert(str(self.plaze['name'])))
        gobject.timeout_add(KEEP_ALIVE_TIME, self.keep_alive)
        return True

    def open_current_plaze(self):
        # Launch browser over DBUS service
        bus = dbus.SessionBus()
        proxy_obj = bus.get_object('com.nokia.osso_browser', '/com/nokia/osso_browser')
        dbus_iface = dbus.Interface(proxy_obj, 'com.nokia.osso_browser')
        return dbus_iface.open_new_window(self.plaze_url)

    def log_out_timeout(self):
        self.log_out()
        return False

    def log_out(self):
        self.label_plazeinfo.set_text(_('Logged out from Plazes'))
        if (self.current_session == False):
            return True
        try:
            stat = self.logoff(self.current_session)
        except:
            # We might not have network (which will raise exception)
            pass
        self.current_session = False

    def logger_initialize(self):
        # Setup text buffer for our log
        self.logwindowview=self.text_plazeslog
        self.logwindow=gtk.TextBuffer(None)
        self.logwindowview.set_buffer(self.logwindow)
        return True

    def log(self, message):
        message = message + "\n"
        self.logwindow.insert_at_cursor(message, len(message))
        # Trying to autoscroll the log seems to cause more issues
        #text_iter = self.logwindow.get_end_iter()
        #self.logwindowview.scroll_to_iter(text_iter, 0.01)

    def on_button_openplaze_clicked(self, *args):
        self.open_current_plaze()

    def on_plaze_clicked(self, *args):
        gobject.timeout_add(1, self.relogin_timeout)

    def get_show_current_plaze(self):
        if (self.plazed == False):
            return self.relogin()
        return self.plaze_nice()

    def on_button_clear_log_clicked(self, *args):
        self.logwindow.delete(self.logwindow.get_start_iter(), self.logwindow.get_end_iter())

    def on_maemoplazer_main_destroy(self, *args):
        self.quit()

    def quit(self):
        try:
            self.log_out()
        except:
            # We might not have network here (which will cause exceptions from XML-RPC layer to bubble up
            pass
        SimpleGladeApp.quit(self)
        
    def on_close_program_activate(self, *args):
        self.window.destroy()

    def dummy_destroy(self, *args):
        pass

## Call our UI
def main( __version__ = None):
    global app_version

    bindtextdomain( app_name, locale_dir)
    app_version = __version__

    m_maemoplazer_ui = maemoplazer_ui()
    m_maemoplazer_ui.run()

## if run as binary, call main
if __name__ == '__main__':
    main()
