#! /usr/bin/env python

#
# firstboot
#
# Copyright (C) 2011  Red Hat, Inc.
#
# 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, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
#

import optparse
import os
import sys
import tempfile
import traceback

import firstboot.frontend
import firstboot.loader

from firstboot.constants import *

# XXX
from firstboot.config import *

import meh
import meh.dump

import gettext
_ = lambda x: gettext.ldgettext("firstboot", x)

def exception_handler(type, value, tb, obj):
    # write exception to a file
    fd, path = tempfile.mkstemp(prefix='/var/tmp/firstboot-', suffix='.trace')
    exception_lines = traceback.format_exception(type, value, tb)
    os.write(fd, "".join(exception_lines))
    os.close(fd)

    meh_conf = meh.Config(programName='firstboot',
                              programVersion='@VERSION@')

    dump_obj = meh.dump.ExceptionDump((type, value, tb), meh_conf)
    exn_dump = dump_obj.traceback_and_object_dump(obj)

    fd, path = tempfile.mkstemp(prefix='firstboot-tb-')
    os.write(fd, exn_dump)
    os.close(fd)

    # that's basically what python-meh's Save button does, except that the
    # following code just creates directories ABRT wants for reporting bug
    import report
    params = dict()
    params.update(dump_obj.environment_info)

    params.setdefault('component', 'firstboot')
    params.setdefault('package', 'firstboot-@VERSION@')

    params['hashmarkername'] = 'firstboot'
    params['duphash'] = dump_obj.hash
    params['reason'] = dump_obj.desc
    params['description'] = 'Traceback from firstboot:\n%s' % str(dump_obj)
    params['firstboot-tb'] = exn_dump
    params['uid'] = "%d" % os.geteuid()

    problem_data = report.createPythonUnhandledExceptionSignature(**params)

    problem_data.create_dump_dir('/var/spool/abrt')

    print _('Unhandled exception in firstboot occured.')
    print _('Bugreport directory was created and once you login, ABRT should\n'
            'let you file a bug. (Don\'t forget to check "Show all problems")')
    answer = raw_input (_('Do you want to start /usr/bin/setup so that you can\n'
                          'create your user account? [Y/n] '))

    if not answer.lower() in [_('n'), _('no')]:
        os.system('/usr/bin/setup')


if __name__ == '__main__':
    # set up exception handling first
    sys.excepthook = lambda ty, value, tb: exception_handler(ty, value, tb,
                                                              config)

    # only root can do this
    if not os.geteuid() == 0:
        print >> sys.stderr, 'only root can do this'
        sys.exit(1)

    parser = optparse.OptionParser()
    parser.add_option('-m', '--moduledir', dest='module_dir')
    parser.add_option('-r', '--reconfig',
                      action='store_true', default=False)
    parser.add_option('-s', '--autoscreenshot',
                      action='store_true', default=False)
    parser.add_option('-t', '--test',
                      action='store_true', default=False)
    parser.add_option('--themedir', dest='theme_dir')

    opts, args = parser.parse_args()

    # XXX should we run?
    if os.path.isfile('/etc/sysconfig/firstboot'):
        with open('/etc/sysconfig/firstboot') as fobj:
            for line in fobj:
                if line.strip() == 'RUN_FIRSTBOOT=NO':
                    os.system('systemctl stop firstboot-graphical.service > /dev/null 2>&1')
                    os.system('systemctl stop firstboot-text.service > /dev/null 2>&1')
                    sys.exit(0)

    if not opts.module_dir:
        opts.module_dir = MODULE_DIR

    if not opts.theme_dir:
        themes = [d for d in os.listdir(THEME_DIR) if d != 'default']
        if themes:
            opts.theme_dir = os.path.join(THEME_DIR, themes[0])
        else:
            opts.theme_dir = os.path.join(THEME_DIR, 'default')

    # XXX set the theme dir in config
    config.themeDir = opts.theme_dir

    frontend = None
    if 'DISPLAY' not in os.environ:
        frontend = firstboot.frontend.Frontend()
        frontend.set_lang()
        frontend.startx()
        frontend.init_gtk()
        frontend.start_wm()
        frontend.merge_xres()

    # these modules import gtk, so we need to have a display first
    import firstboot.interface

    # XXX set up the interface
    config.frontend = frontend
    config.interface = firstboot.interface.Interface(opts.autoscreenshot,
                                                     opts.test)

    # load modules
    loader = firstboot.loader.Loader()
    modules = loader.load_modules(module_dir=opts.module_dir,
                                  reconfig=opts.reconfig)

    if not modules:
        err = 'no modules found'
        raise RuntimeError(err)

    # TODO rewrite the interface
    config.interface.moduleList = modules
    config.interface.createMainWindow()
    config.interface.createScreens()
    config.interface.createSidebar()
    config.interface.run()

    if frontend is not None:
        frontend.kill()

    if not opts.test:
        with open('/etc/sysconfig/firstboot', 'w') as f:
            f.write('RUN_FIRSTBOOT=NO\n')

        if opts.reconfig:
            try:
                os.unlink('/etc/reconfigSys')
            except OSError:
                pass
