#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2007-2011 Zuza Software Foundation
# Copyright 2013,2015 F Wolff
#
# This file is part of Virtaal.
#
# 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/>.

import sys
from os import path

from virtaal.common import pan_app

# Some behaviour should vary, depending on whether Virtaal is packaged or not
packaged = getattr(sys, 'frozen', False)
# Distributions can just set this value to True, if dependencies are taken care
# of elsewhere:
#packaged = True

# Let's check for dependencies before we do anything else
if not packaged:
    # We can't meaningfully report on these, and we build our own windows
    # version, so let's leave this out for the benefit of startup time.
    from virtaal.support import depcheck
    optional_modules = ['enchant', 'gtkspell', 'psycopg2', 'libproxy']
    error_messages = {
        'translate':  'Translate Toolkit >= %s is required for Virtaal to function.' % str(depcheck.MIN_TRANSLATE_VERSION),
        'gtk':        'Gtk >= %s and PyGTK is required for Virtaal to function.' % str(depcheck.MIN_GTK_VERSION),
        'lxml.etree': 'LXML is required for XML-based format support as well as AutoCorrection.',
        'json':       'SimpleJSON or Python >= 2.6 is required for certain TM back-ends.',
        'pycurl':     'PyCurl is required for certain TM and terminology back-ends.',
        'sqlite3':    'SQLite3 is required for Virtaal to function.',
        'wsgiref':    'WSGIRef is required for Virtaal to function.',
        'enchant':    'Enchant not installed: Spell checking will not work.',
        'gtkspell':   'GtkSpell not installed: Spell checking will not work.',
        'psycopg2':   'PsycoPG not installed: The TinyTM plug-in will not work.',
        'libproxy':   'libproxy is not installed: it improves support for network proxies on Linux.',
        'diff_match_patch': 'diff_match_patch is not installed: it is required for TM functionality.',
    }

    failed = depcheck.check_dependencies(depcheck.import_checks + optional_modules)
    if failed:
        errors = '\n'.join([error_messages[name] for name in failed if name in depcheck.import_checks])
        warnings = '\n'.join([error_messages[name] for name in failed if name in optional_modules])

        if warnings:
            print('DEPENDENCY WARNINGS:')
            print(warnings)
        if errors:
            print('DEPENDENCY ERRORS:')
            print(errors)
        print()
        print("You can disable dependency checking to speed up startup by setting")
        print("  packaged = True")
        print("in the file '%s'" % __file__)
        if errors:
            sys.exit(1)
# OK, dependencies seem to be acceptable

def run_virtaal(startup_file):
    # The Virtaal class is imported here to allow changes made in this script (eg. pan_app.DEBUG)
    # to be visible to the rest of the program, seeing as Virtaal imports all controllers, which
    # basically imports the the whole core.
    from virtaal.main import Virtaal
    prog = Virtaal(startup_file)
    prog.run()


def main(argv):
    options = None
    parser = None
    startup_file = None

    if len(argv) > 1:
        import optparse
        from optparse import OptionParser, make_option

        from virtaal import __version__

        optparse._ = _
        usage = _("%prog [options] [translation_file]")
        option_list = [
            make_option("-l", "--log",
                        action="store", type="string", dest="log", metavar=_("LOG"),
                        help=_("turn on logging, storing the result to the supplied filename.")),
            make_option("-c", "--config",
                        action="store", type="string", dest="config", metavar=_("CONFIG"),
                        help=_("use the configuration file given by the supplied filename.")),
            make_option("-D", "--debug",
                        action="store_true", dest="debug", default=False,
                        help=_("enable debugging features")),
        ]
        # Profiling does not make sense in packaged versions.  Set to True to disable profiling.
        if not packaged:
            option_list.insert(0, make_option("-P", "--profile", action="store",
                                              type="string", dest="profile",
                                              metavar=_("PROFILE"),
                                              #l10n: 'profiling' refers to performance testing
                                              help=_("perform profiling, storing the result to the supplied filename.")))
        parser = OptionParser(option_list=option_list, usage=usage, version=__version__.ver)


        def set_logging(options):
            if options.log is None and not options.debug:
                return

            import logging
            level = options.debug and logging.DEBUG or logging.INFO
            if options.debug:
                format = '%(levelname)7s %(module)s.%(funcName)s:%(lineno)d: %(message)s'
                if sys.version_info[:2] < (2, 5):
                    format = '%(levelname)7s %(module)s [%(filename)s:%(lineno)d]: %(message)s'
            else:
                format = '%(asctime)s %(levelname)s %(message)s'
            if options.log is None:
                logging.basicConfig(level=level, format=format, stream=sys.stderr)
            elif options.log.upper() in ('-', 'STDOUT'):
                logging.basicConfig(level=level, format=format, stream=sys.stdout)
            else:
                try:
                    logging.basicConfig(level=level, format=format, filename=path.abspath(options.log), filemode='w')
                except IOError:
                    parser.error(_("Could not open log file '%(filename)s'") % {"filename": options.log})


        def set_config(options):
            try:
                if options.config != None:
                    pan_app.settings = pan_app.Settings(path.abspath(options.config))
            except:
                parser.error(_("Could not read configuration file '%(filename)s'") % {"filename": options.config})

        def get_startup_file(options):
            if len(args) > 1:
                parser.error(_("invalid number of arguments"))
            elif len(args) == 1:
                return args[0]
            else:
                return None


        options, args = parser.parse_args(argv[1:])
        pan_app.DEBUG = options.debug
        set_config(options)
        set_logging(options)
        startup_file = get_startup_file(options)
    else:
        # No arguments given, so we save some time by avoiding all the things
        # that could have happened on the command line
        pan_app.DEBUG = False

    def get_virtaal_runner(options):
        def profile_runner(startup_file):
            def profile(profile_file, startup_file):
                import cProfile
                import logging
                try:
                    import devsupport.profiling as profiling
                except ImportError:
                    #l10n: This refers to performance profiling for developers
                    logging.error(_("Profiling support is not available"))
                    sys.exit(1)
                logging.info('Starting profiling run')
                profiler = cProfile.Profile()
                profiler.runcall(run_virtaal, startup_file)
                k_cache_grind = profiling.KCacheGrind(profiler)
                k_cache_grind.output(profile_file)
                profile_file.close()

            try:
                profile(open(options.profile, 'w+'), startup_file)
            except IOError:
                parser.error(_("Could not open profile file '%(filename)s'") % {"filename":options.profile})

        def default_runner(startup_file):
            if not pan_app.DEBUG:
                try:
                    import psyco
                    psyco.full()
                except Exception:
                    pass
            run_virtaal(startup_file)

        if options and getattr(options, "profile", None) != None:
            return profile_runner
        else:
            return default_runner

    runner = get_virtaal_runner(options)
    runner(startup_file)

if __name__ == "__main__":
    main(sys.argv)
