#!/usr/bin/python3

import gettext
import os
import subprocess
import sys
import traceback
import rpm
import scout
sys.path.append(scout.Config.module_path)
import bin

_ = gettext.gettext

EX_NOTFOUND = 127
SUDO_CMD = ['sudo']
INSTALL_CMD = ['zypper', 'install']

gettext.bindtextdomain('command-not-found', localedir='/usr/share/locale')
gettext.textdomain(domain='command-not-found')


def print_found(rows, term):
    print(file=sys.stderr)
    print(gettext.ngettext(
        "The program '{prog}' can be found in the following package:",
        "The program '{prog}' can be found in following packages:",
        len(rows)).format(prog=term), file=sys.stderr)

    for row in rows:
        print(_('  * {prog} [ path: {path}/{binary}, repository: {repo} ]')
              .format(repo=row[0], prog=row[1], path=row[2], binary=row[3]),
              file=sys.stderr)
    print(file=sys.stderr)
    print(_('Try installing with:\n   '), end=' ', file=sys.stderr)
    installcmd = INSTALL_CMD
    if os.getuid() != 0:
        installcmd = SUDO_CMD + installcmd
    if len(set([i[1] for i in rows])) > 1:
        print(" ".join(installcmd), _('<selected_package>'), file=sys.stderr)
    else:
        installcmd.append(rows[0][1])
        print(" ".join(installcmd), file=sys.stderr)
        if os.getenv("COMMAND_NOT_FOUND_INSTALL"):
            print(_("Running the command now"), file=sys.stderr)
            subprocess.call(installcmd, shell=False)
    print(file=sys.stderr)
    sys.exit(0)


def print_installed(term, pkg, path):
    print(file=sys.stderr)
    print(_("Program '{prog}' is present in package '{pkg}', "
            'which is installed on your system.')
          .format(prog=term, pkg=pkg), file=sys.stderr)
    print(file=sys.stderr)
    if '/sbin' in path:
        print(_("Absolute path to '{prog}' is '{path}/{prog}', "
                'so running it may require superuser privileges (eg. root).')
              .format(prog=term, path=path), file=sys.stderr)
    else:
        print(_("Absolute path to '{prog}' is '{path}/{prog}'. "
                'Please check your $PATH variable to see whether it '
                'contains the mentioned path.')
              .format(prog=term, path=path), file=sys.stderr)
    print(file=sys.stderr)
    sys.exit(0)


def check_installed(term, pkg, path):
    if not os.path.isfile('{path}/{term}'.format(path=path, term=term)):
        return False
    ts = rpm.TransactionSet()
    mi = ts.dbMatch('name', pkg)
    return mi.count() > 0


def find_package_by_file(term):
    ts = rpm.TransactionSet()
    mi = ts.dbMatch('basenames', term)
    try:
        ret = next(mi)['name']
        if isinstance(ret, str):
            return ret
        else:
            return ret.decode()
    except StopIteration:
        return None


def main():
    if len(sys.argv) < 2:
        sys.exit(EX_NOTFOUND)

    default_lang = scout.DefaultLang(textdomain='command-not-found')
    default_lang.install()

    term = sys.argv[1]
    print('{term}:'.format(term=term), _('searching ...'), end=' ', file=sys.stderr)
    lendel = len(term) + 3 + len(_('searching ...'))

    for path in ('/usr/sbin', '/sbin'):
        pkg = find_package_by_file(path + '/' + term)
        if pkg:
            print('\r', lendel * ' ', end=' ', file=sys.stderr)
            print_installed(term, pkg, path)
            sys.exit(EX_NOTFOUND)

    if len(sys.argv) == 3:
        repo = sys.argv[2]
    else:
        repo = 'zypp'

    module = bin.ScoutModule()
    if repo == 'zypp':
        rows = module.query_zypp(term)
    else:
        rows = module.query_repo(repo, term)

    if not rows:
        print('\r', '{term}:'.format(term=term), _('command not found'),
              lendel * ' ', file=sys.stderr)
        sys.exit(EX_NOTFOUND)

    print('\r', lendel * ' ', end=' ', file=sys.stderr)

    for row in rows:
        if check_installed(term, row[1], row[2]):
            print_installed(term, row[1], row[2])

    print_found(rows, term)


if __name__ == "__main__":
    try:
        main()
    except Exception:
        traceback.print_exc()
        sys.exit(EX_NOTFOUND)
