#!/usr/bin/python3

# Copyright (C) 2013  ABRT Team
# Copyright (C) 2013  Red Hat, Inc.
#
# This file is part of faf.
#
# faf 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 3 of the License, or
# (at your option) any later version.
#
# faf 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 faf.  If not, see <http://www.gnu.org/licenses/>.

import os
import re
import sys
from argcomplete import autocomplete


# Re-execute self with LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$FAF_LD_LIBRARY_PATH
# if FAF_LD_LIBRARY_PATH is set. This is necessary for OpenShift where
# LD_LIBRARY_PATH is already set, but does not include satyr.
# This needs to be done before the first import of pyfaf.

FAF_LD_LIBRARY_PATH = "FAF_LD_LIBRARY_PATH"
LD_LIBRARY_PATH = "LD_LIBRARY_PATH"
OPENSHIFT_FAF_DIR = "OPENSHIFT_FAF_DIR"

def fix_ld_library_path():
    if os.getenv("FAF_OPENSHIFT_LD_FIXED") is not None:
        return
    faf_ld_library_path = os.getenv(FAF_LD_LIBRARY_PATH)
    if faf_ld_library_path is None:
        openshift_faf_dir = os.getenv(OPENSHIFT_FAF_DIR)
        if openshift_faf_dir is None:
            return
        faf_ld_library_path = os.path.join(openshift_faf_dir,
                                           "root", "usr", "lib64")

    ld_library_path = os.getenv(LD_LIBRARY_PATH)
    if ld_library_path is None:
        os.environ[LD_LIBRARY_PATH] = faf_ld_library_path
    else:
        new_path = os.pathsep.join([ld_library_path, faf_ld_library_path])
        os.environ[LD_LIBRARY_PATH] = new_path

    os.environ["FAF_OPENSHIFT_LD_FIXED"] = "1"
    os.execvpe(sys.argv[0], sys.argv, os.environ)

fix_ld_library_path()

# pylint: disable=wrong-import-position
import pyfaf
from pyfaf.cmdline import CmdlineParser
from pyfaf.config import config
from pyfaf.common import Plugin, log, load_plugins
from pyfaf.storage import getDatabase
from pyfaf.utils.parse import str2bool

NAME_PARSER = re.compile(r"^faf-([^{0}]+)$".format(os.sep))


def main():
    name_match = NAME_PARSER.match(os.path.basename(sys.argv[0]))
    if name_match is not None:
        sys.argv[0] = os.path.join(os.path.dirname(sys.argv[0]), "faf")
        sys.argv.insert(1, name_match.group(1))

    cmdline_parser = CmdlineParser(toplevel=True,
                                   desc="Perform a FAF action",
                                   prog=sys.argv[0])
    cmdline_parser.add_argument("-V", "--version", action="store_true",
                                help="show version information and exit")
    autocomplete(cmdline_parser)
    cmdline = cmdline_parser.parse_args()

    # print version and quit
    if cmdline.version:
        print("ABRT Analytics v{}".format(pyfaf.__version__))
        sys.exit(0)

    if not hasattr(cmdline, "func"):
        log.error("No command specified")
        cmdline_parser.print_help()
        sys.exit(1)

    # Catching too general exception Exception
    # pylint: disable-msg=W0703

    # connect to the database
    try:
        db = getDatabase(debug=cmdline.sql_verbose, dry=cmdline.dry_run)
    except Exception as ex:
        log.critical("Unable to connect to the database: %s: %s",
                     ex.__class__.__name__, str(ex))

        if cmdline.debug:
            raise

        sys.exit(1)

    # auto-enable plugins
    if str2bool(config["main.autoenableplugins"]):
        plugins = set()
        for cls in Plugin.__subclasses__():
            plugins |= set(load_plugins(cls, init=False, debug=cmdline.debug).values())

        for plugin in plugins:
            try:
                if not plugin.installed(db):
                    log.debug("Automatically installing plugin %s", plugin.__name__)
                    logger = log.getChild(plugin.__name__)
                    plugin.install(db, logger=logger)
            except Exception as ex:
                log.critical("Unable to enable plugin %s: %s: %s", plugin.__name__,
                             ex.__class__.__name__, str(ex))

                if cmdline.debug:
                    raise

                sys.exit(1)

    # execute the command
    try:
        exitcode = cmdline.func(cmdline, db)

        if exitcode is None:
            sys.exit(0)

        if not isinstance(exitcode, int):
            log.warning("Action returned a suspicious exit code. Expected "
                        "'int', got '%s'", type(exitcode).__name__)
            sys.exit(1)

        sys.exit(exitcode)
    except Exception as ex:
        log.critical("Action failed unexpectedly: %s: %s", ex.__class__.__name__, str(ex))
        log.debug("Backtrace:", exc_info=True)

        sys.exit(1)

if __name__ == "__main__":
    main()
