#!/usr/bin/env python
# Copyright (C) 2006, Red Hat, Inc.
# Copyright (C) 2009, One Laptop Per Child Association Inc
# Copyright (C) 2010, Plan Ceibal <comunidad@plan.ceibal.edu.uy>
# Copyright (C) 2011, OLPC-AU.
#
# 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 2 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import os
import sys
import time
import subprocess
import shutil

if os.environ.get('SUGAR_LOGGER_LEVEL', '') == 'debug':
    print '%r STARTUP: Starting the shell' % time.time()
    sys.stdout.flush()

import gettext
import logging

import gconf
import gtk
import gobject
import dbus.glib
import wnck

try:
    import xklavier
except ImportError:
    logging.debug('Could not load xklavier for keyboard configuration')

gtk.gdk.threads_init()
dbus.glib.threads_init()

def cleanup_logs(logs_dir):
    """Clean up the log directory, moving old logs into a numbered backup
    directory.  We only keep `_MAX_BACKUP_DIRS` of these backup directories
    around; the rest are removed."""
    if not os.path.isdir(logs_dir):
        os.makedirs(logs_dir)

    backup_logs = []
    backup_dirs = []
    for f in os.listdir(logs_dir):
        path = os.path.join(logs_dir, f)
        if os.path.isfile(path):
            backup_logs.append(f)
        elif os.path.isdir(path):
            backup_dirs.append(path)

    if len(backup_dirs) > 3:
        backup_dirs.sort()
        root = backup_dirs[0]
        for f in os.listdir(root):
            os.remove(os.path.join(root, f))
        os.rmdir(root)

    if len(backup_logs) > 0:
        name = str(int(time.time()))
        backup_dir = os.path.join(logs_dir, name)
        os.mkdir(backup_dir)
        for log in backup_logs:
            source_path = os.path.join(logs_dir, log)
            dest_path = os.path.join(backup_dir, log)
            os.rename(source_path, dest_path)

def start_ui_service():
    from jarabe.view.service import UIService

    ui_service = UIService()

def start_session_manager():
    from jarabe.model.session import get_session_manager

    session_manager = get_session_manager()
    session_manager.start()

def unfreeze_dcon_cb():
    logging.debug('STARTUP: unfreeze_dcon_cb')
    from jarabe.model import screen

    screen.set_dcon_freeze(0)

def setup_frame_cb():
    logging.debug('STARTUP: setup_frame_cb')
    from jarabe import frame
    frame.get_view()

def setup_keyhandler_cb():
    logging.debug('STARTUP: setup_keyhandler_cb')
    from jarabe.view import keyhandler
    from jarabe import frame
    keyhandler.setup(frame.get_view())

def setup_journal_cb():
    logging.debug('STARTUP: setup_journal_cb')
    from jarabe.journal import journalactivity
    journalactivity.start()

def show_software_updates_cb():
    logging.debug('STARTUP: show_software_updates_cb')
    if os.path.isfile(os.path.expanduser('~/.sugar-update')):
        from jarabe.desktop import homewindow
        home_window = homewindow.get_instance()
        home_window.get_home_box().show_software_updates_alert()

def setup_notification_service_cb():
    from jarabe.model import notifications
    notifications.init()

def setup_file_transfer_cb():
    from jarabe.model import filetransfer
    filetransfer.init()

def setup_keyboard_cb():
    logging.debug('STARTUP: setup_keyboard_cb')

    gconf_client = gconf.client_get_default()
    have_config = False

    try:
        display = gtk.gdk.display_get_default()
        if display is not None:
            engine = xklavier.Engine(display)
        else:
            logging.debug('setup_keyboard_cb: Could not get default display.')
            return

        configrec = xklavier.ConfigRec()
        configrec.get_from_server(engine)

        layouts = gconf_client.get_list(\
            '/desktop/sugar/peripherals/keyboard/layouts', gconf.VALUE_STRING)
        layouts_list = []
        variants_list = []
        for layout in layouts:
            layouts_list.append(layout.split('(')[0])
            variants_list.append(layout.split('(')[1][:-1])

        if layouts_list and variants_list:
            have_config = True
            configrec.set_layouts(layouts_list)
            configrec.set_variants(variants_list)

        model = gconf_client.get_string(\
            '/desktop/sugar/peripherals/keyboard/model')
        if model:
            have_config = True
            configrec.set_model(model)

        options = gconf_client.get_list(\
            '/desktop/sugar/peripherals/keyboard/options', gconf.VALUE_STRING)
        if options:
            have_config = True
            configrec.set_options(options)

        if have_config:
            configrec.activate(engine)
    except Exception:
        logging.exception('Error during keyboard configuration')

def setup_window_manager():
    logging.debug('STARTUP: window_manager')

    # have to reset cursor(metacity sets it on startup)
    if subprocess.call('echo $DISPLAY; xsetroot -cursor_name left_ptr', shell=True):
        logging.warning('Can not reset cursor')

    if subprocess.call('metacity-message disable-keybindings',
            shell=True):
        logging.warning('Can not disable metacity keybindings')

def bootstrap():
    setup_window_manager()

    from jarabe.view import launcher
    launcher.setup()

    gobject.idle_add(setup_frame_cb)
    gobject.idle_add(setup_keyhandler_cb)
    gobject.idle_add(setup_journal_cb)
    gobject.idle_add(setup_notification_service_cb)
    gobject.idle_add(setup_file_transfer_cb)
    gobject.idle_add(show_software_updates_cb)
    gobject.idle_add(setup_accessibility_cb)

    if sys.modules.has_key('xklavier'):
        gobject.idle_add(setup_keyboard_cb)

def set_fonts():
    client = gconf.client_get_default()
    face = client.get_string('/desktop/sugar/font/default_face')
    size = client.get_float('/desktop/sugar/font/default_size')
    settings = gtk.settings_get_default()
    settings.set_property("gtk-font-name", "%s %f" % (face, size))

def setup_accessibility_cb():
    from jarabe.model import accessibility
    accessibility_manager = accessibility.AccessibilityManager()
    accessibility_manager.setup_accessibility()


def export_proxy_settings():
    """Export manual proxy settings from GConf as environment variables

    Some applications and tools and even some parts of Sugar will use
    the http_proxy environment variable if set, but don't use the Gnome
    (GConf) proxy settings.
    """
    yumtmp = open("/tmp/yum.conf.mod", "w")
    client = gconf.client_get_default()
    if client.get_string('/system/proxy/mode') != 'manual':
        yumtmp.close()
        return

    http_host = client.get_string('/system/http_proxy/host')
    http_port = client.get_int('/system/http_proxy/port')
    use_auth = client.get_bool('/system/http_proxy/use_authentication')
    proxy_info = '%s:%d' % (http_host, http_port)
    yumtmp.write('proxy=http://%s/\n' % proxy_info)
    if use_auth:
        user = client.get_string('/system/http_proxy/authentication_user')
        pword = client.get_string('/system/http_proxy/authentication_password')
	yumtmp.write('proxy_username %s\n' % user)
	yumtmp.write('proxy_password %s\n' % pword)
        proxy_info = '%s:%s@%s' % (user, pword, proxy_info)

    os.environ['http_proxy'] = 'http://%s/' % proxy_info
    yumtmp.close()


def main():
    try:
        from sugar import env
        # Remove temporary files. See http://bugs.sugarlabs.org/ticket/1876
        data_dir = os.path.join(env.get_profile_path(), 'data')
        shutil.rmtree(data_dir, ignore_errors=True)
        os.makedirs(data_dir)
        cleanup_logs(env.get_logs_path())
    except OSError, e:
        # logs cleanup is not critical; it should not prevent sugar from
        # starting if (for example) the disk is full or read-only.
        print 'logs cleanup failed: %s' % e

    from sugar import logger
    # NOTE: This needs to happen so early because some modules register translatable
    # strings in the module scope.
    from jarabe import config
    gettext.bindtextdomain('sugar', config.locale_path)
    gettext.bindtextdomain('sugar-toolkit', config.locale_path)
    gettext.textdomain('sugar')

    from jarabe.desktop import homewindow
    from jarabe.model import sound, feedback_collector
    from jarabe import intro

    logger.start('shell')

    client = gconf.client_get_default()
    client.set_string('/apps/metacity/general/mouse_button_modifier',
                      '<Super>')

    if client.get_bool('/desktop/sugar/feedback/personalized_submit') or \
            client.get_int('/desktop/sugar/feedback/anonymous_delay'):
        feedback_collector.start(
                client.get_string('/desktop/sugar/feedback/server_host'),
                client.get_int('/desktop/sugar/feedback/server_port'),
                client.get_int('/desktop/sugar/feedback/anonymous_delay'))

    timezone = client.get_string('/desktop/sugar/date/timezone')
    if timezone is not None and timezone:
        os.environ['TZ'] = timezone

    export_proxy_settings()
    set_fonts()

    # this must be added early, so that it executes and unfreezes the screen
    # even when we initially get blocked on the intro screen
    gobject.idle_add(unfreeze_dcon_cb)

    # make sure we have the correct cursor in the intro screen
    # TODO #3204
    if subprocess.call('echo $DISPLAY; xsetroot -cursor_name left_ptr', shell=True):
        logging.warning('Can not reset cursor')
    intro.check_profile()

    start_ui_service()
    start_session_manager()

    sound.restore()

    sys.path.append(config.ext_path)

    icons_path = os.path.join(config.data_path, 'icons')
    gtk.icon_theme_get_default().append_search_path(icons_path)

    # open homewindow before window_manager to let desktop appear fast
    home_window = homewindow.get_instance()
    home_window.show()

    screen = wnck.screen_get_default()
    screen.connect('window-manager-changed', __window_manager_changed_cb)
    _check_for_window_manager(screen)

    try:
        gtk.main()
    except KeyboardInterrupt:
        print 'Ctrl+C pressed, exiting...'


def __window_manager_changed_cb(screen):
    _check_for_window_manager(screen)


def _check_for_window_manager(screen):
    wm_name = screen.get_window_manager_name()
    if wm_name is not None:
        screen.disconnect_by_func(__window_manager_changed_cb)
        bootstrap()


main()
