#!/usr/bin/python2 -O
# -*- coding: utf-8 -*-
"""

    @author: Fabio Erculiani <lxnay@sabayon.org>
    @contact: lxnay@sabayon.org
    @copyright: Fabio Erculiani
    @license: GPL-2

    B{Entropy Package Manager Server Wrapper Tool}.

"""
import os
import sys
import subprocess
sys.path.insert(0, '../libraries')
sys.path.insert(1, '../client')
sys.path.insert(2, '../server')
sys.path.insert(3, '/usr/lib/entropy/client')
sys.path.insert(4, '/usr/lib/entropy/libraries')
sys.path.insert(5, '/usr/lib/entropy/server')

from entropy.i18n import _
import entropy.tools
from text_tools import print_menu
from entropy.output import is_stdout_a_tty, nocolor, print_error, print_info, \
    print_warning, purple, teal
from entropy.const import etpConst, etpUi

REAGENT_EXEC = "/usr/sbin/reagent"
ACTIVATOR_EXEC = "/usr/sbin/activator"

help_opts = [
    None,
    (0, " ~ eit ~ ", 1,
        'The Stupid Entropy Content Tracker (wrapper) - (C) %s' % (
            entropy.tools.get_year(),) ),
    None,
    (0, _('Options'), 0, None),
    None,
    (1, 'add <pkgs>', 3, _('commit to current repository only the provided packages')),
    (1, 'addto <repository> <pkgs>', 1, _('commit to give repository only the provided packages')),
    (1, 'bump [<repository>]', 2, _('bump repository revision, this will force upload')),
    (1, 'checkout <repository>', 2, _('switch from a repository to another')),
    (1, 'cleanup [<repository>]', 2, _('clean expired packages from a repository')),
    (1, 'commit [<repository>]', 2, _('commit changes to repository')),
    (1, 'cp <from> <to> <pkgs>', 2, _('copy packages from a repository to another')),
    (1, 'deps <pkgs>', 3, _('edit package dependencies')),
    (1, 'depsin <repository> <pkgs>', 1, _('edit package dependencies in given repository')),
    (1, 'deptest [<repository>]', 2, _('edit package dependencies')),
    (1, 'fit <package files>', 2, _('inject package files into the current repository')),
    (1, 'graph <pkgs> [--complete]', 1, _('show dependency graph of packages')),
    (1, 'init <repository>', 2, _('initialize repository (erasing all its content)')),
    (1, 'libtest [--dump]', 2, _('look for missing libraries (scan system)')),
    (1, 'linktest [<excl libs>]', 2, _('look for missing libraries (scan repository metadata)')),
    (1, 'list [<repository>]', 2, _('list packages in repository')),
    (1, 'log [<repository>]', 2, _('show log for repository')),
    (1, 'mv <from> <to> <pkgs>', 2, _('move packages from a repository to another')),
    (1, 'own <package files>', 2, _('show owners of files (in current repository)')),
    (1, 'push [<repository>]', 2, _('push committed packages remotely')),
    (1, 'pushas <repository> <as repo>', 1, _('push committed packages to given fake repository')),
    (1, 'repack <pkgs>', 3, _('re-package list of packages in default repository')),
    (1, 'repackin <repository> <pkgs>', 1, _('re-package list of packages in given repository')),
    (1, 'repo', 4, _('show current repository')),
    (1, 'reset [<repository>]', 2, _('reset repository to remote status')),
    (1, 'revgraph <pkgs> [--complete]', 1, _('show reverse dependency graph of packages')),
    (1, 'rm <pkgs>', 3, _('remove packages from current repository')),
    (1, 'rmfrom <repository> <pkgs>', 1, _('remove packages from given repository')),
    (1, 'search <package deps>', 2, _('search for privided package dependencies')),
    (1, 'show <package deps>', 2, _('show matches for privided package dependencies')),
    (1, 'status [<repository>]', 2, _('show current repositories status')),
    (1, 'vacuum [<repository>]', 2, _('clean unavailable packages from a repository')),
    None,
]

options = sys.argv[1:]

import re
opt_r = re.compile("^(\\-)([a-z]+)$")
for n in range(len(options)):
    if opt_r.match(options[n]):
        x = options[n]
        del options[n]
        options.extend(["-%s" % (d,) for d in x[1:]])

# preliminary options parsing
_options = []
no_color = False
force_color = False
for opt in options:
    if opt in ["--nocolor", "-N"]:
        nocolor()
        no_color = True
    elif opt in ["--color", "-C"]:
        force_color = True
    elif opt in ["--quiet", "-q"]:
        etpUi['quiet'] = True
    elif opt in ["--verbose", "-v"]:
        etpUi['verbose'] = True
    elif opt in ["--ask", "-a"]:
        etpUi['ask'] = True
    elif opt in ["--pretend", "-p"]:
        etpUi['pretend'] = True
    else:
        _options.append(opt)
options = _options

# Check if we need to disable colors
if (not force_color) and (not is_stdout_a_tty()):
    nocolor()

# print help
if not options or ("--help" in options) or ("-h" in options):
    print_menu(help_opts)
    if len(options) < 1:
        print_error("not enough parameters")
        raise SystemExit(1)
    raise SystemExit(0)

def _exec_args(args):
    myargs = []
    if etpUi['quiet']:
        myargs.append("--quiet")
    if etpUi['verbose']:
        myargs.append("--verbose")
    if etpUi['ask']:
        myargs.append("--ask")
    if etpUi['pretend']:
        myargs.append("--pretend")
    if force_color:
        myargs.append("--color")
    if no_color:
        myargs.append("--nocolor")
    os.execvpe(args[0], args + myargs, os.environ)

def get_entropy_server(quiet = False):
    oldquiet = etpUi['quiet']
    try:
        if quiet:
            etpUi['quiet'] = True
        from entropy.server.interfaces import Server
        return Server(community_repo = etpConst['community']['mode'])
    finally:
        if quiet:
            etpUi['quiet'] = oldquiet

def _get_available_repositories():
    server = None
    try:
        server = get_entropy_server(quiet = True)
        repository_ids = server.repositories()
        return repository_ids
    finally:
        if server is not None:
            server.shutdown()

main_cmd = options.pop(0)

if main_cmd == "status":
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            os.environ['ETP_REPO'] = options.pop(0)
    _exec_args([REAGENT_EXEC, "status"] + options)

elif main_cmd == "add" and options:
    _exec_args([REAGENT_EXEC, "update", "--atoms"] + options)

elif main_cmd == "addto" and options and len(options) > 1:
    avail_repos = _get_available_repositories()
    if options[0] in avail_repos:
        os.environ['ETP_REPO'] = options.pop(0)
        _exec_args([REAGENT_EXEC, "update", "--atoms"] + options)

elif main_cmd == "repack" and options:
    _exec_args([REAGENT_EXEC, "update", "--atoms"] + options + \
        ["--repackage"] + options)

elif main_cmd == "repackin" and options and len(options) > 1:
    avail_repos = _get_available_repositories()
    if options[0] in avail_repos:
        os.environ['ETP_REPO'] = options.pop(0)
        _exec_args([REAGENT_EXEC, "update", "--atoms"] + options + \
            ["--repackage"] + options)

elif main_cmd == "bump":
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            os.environ['ETP_REPO'] = options.pop(0)
    _exec_args([REAGENT_EXEC, "repo", "bump"])

elif (main_cmd == "checkout") and options and len(options) < 2:
    repository_id = options.pop(0)
    _exec_args([REAGENT_EXEC, "repo", "default", repository_id])

elif main_cmd == "cleanup":
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            os.environ['ETP_REPO'] = options.pop(0)
    _exec_args([ACTIVATOR_EXEC, "tidy"])

elif main_cmd == "vacuum":
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            os.environ['ETP_REPO'] = options.pop(0)
    _exec_args([ACTIVATOR_EXEC, "repo", "vacuum"])

elif main_cmd == "commit":
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            os.environ['ETP_REPO'] = options.pop(0)
            _exec_args([REAGENT_EXEC, "update"] + options)
    else:
        _exec_args([REAGENT_EXEC, "update"] + options)

elif (main_cmd == "fit") and options:
    _exec_args([REAGENT_EXEC, "inject"] + options)

elif main_cmd == "list":
    myopts = []
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            myopts += [options[0]]
    _exec_args([REAGENT_EXEC, "query", "list"] + myopts)

elif main_cmd == "graph" and options and \
    not ((len(set(options)) == 1) and ("--complete" in options)):
    _exec_args([REAGENT_EXEC, "query", "graph"] + options)

elif main_cmd == "revgraph" and options and \
    not ((len(set(options)) == 1) and ("--complete" in options)):
    _exec_args([REAGENT_EXEC, "query", "revgraph"] + options)

elif (main_cmd == "init") and options and len(options) < 2:
    repository_id = options.pop(0)
    avail_repos = _get_available_repositories()
    if repository_id in avail_repos:
        os.environ['ETP_REPO'] = repository_id
        _exec_args([REAGENT_EXEC, "repo", "init"])

elif main_cmd == "libtest":
    lt_options = []
    if "--dump" in options:
        lt_options.append("--dump")
    _exec_args([REAGENT_EXEC, "libtest"] + lt_options)

elif main_cmd == "linktest":
    _exec_args([REAGENT_EXEC, "linktest"] + options)

elif main_cmd == "deptest":
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            os.environ['ETP_REPO'] = options.pop(0)
    _exec_args([REAGENT_EXEC, "deptest"])

elif (main_cmd == "own") and options:
    _exec_args([REAGENT_EXEC, "query", "belongs"] + options)

elif main_cmd == "push":
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            os.environ['ETP_REPO'] = options.pop(0)
    _exec_args([ACTIVATOR_EXEC, "sync"] + options)

elif main_cmd == "pushas" and len(options) == 2:
    avail_repos = _get_available_repositories()
    if options[0] in avail_repos:
        os.environ['ETP_REPO'] = options.pop(0)
        _exec_args([ACTIVATOR_EXEC, "syncas"] + options)

elif main_cmd == "show" and options:
    _exec_args([REAGENT_EXEC, "query", "match"] + options)

elif main_cmd == "search" and options:
    _exec_args([REAGENT_EXEC, "query", "search"] + options)

elif main_cmd == "mv" and len(options) > 2:
    from_repo = options.pop(0)
    to_repo = options.pop(0)
    _exec_args([REAGENT_EXEC, "repo", "move", from_repo, to_repo] + options)

elif main_cmd == "cp" and len(options) > 2:
    avail_repos = _get_available_repositories()
    from_repo = options.pop(0)
    to_repo = options.pop(0)
    if (from_repo in avail_repos) and (to_repo in avail_repos):
        _exec_args([REAGENT_EXEC, "repo", "copy", from_repo, to_repo] + options)

elif main_cmd == "deps" and options:
    server = None
    repository_id = None
    try:
        server = get_entropy_server(quiet = True)
        # get current repository id
        repository_id = server.repository()
    finally:
        if server is not None:
            server.shutdown()

    _exec_args([REAGENT_EXEC, "repo", "package-dep", repository_id] + options)

elif main_cmd == "depsin" and len(options) > 1:
    avail_repos = _get_available_repositories()
    repository_id = options.pop(0)
    if repository_id in avail_repos:
        _exec_args([REAGENT_EXEC, "repo", "package-dep", repository_id] + options)

elif main_cmd == "rm" and options:
    _exec_args([REAGENT_EXEC, "repo", "remove"] + options)

elif main_cmd == "rmfrom" and options and len(options) > 1:
    avail_repos = _get_available_repositories()
    if options[0] in avail_repos:
        os.environ['ETP_REPO'] = options.pop(0)
        _exec_args([REAGENT_EXEC, "repo", "remove"] + options)

elif main_cmd == "repo":
    server = None
    try:
        server = get_entropy_server(quiet = True)
        repository_id = server.repository()
        repository_ids = server.repositories()
        for repo_id in sorted(repository_ids):
            if repo_id == repository_id:
                print_warning(purple(repo_id) + " *")
            else:
                print_info(teal(repo_id))
        raise SystemExit(0)
    finally:
        if server is not None:
            server.shutdown()

elif main_cmd == "reset":
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            os.environ['ETP_REPO'] = options.pop(0)

    server = None
    try:
        server = get_entropy_server()
        rev_path = server._get_local_repository_revision_file(
            server.repository())
        try:
            with open(rev_path, "w") as rev_f:
                rev_f.write("0\n")
        except (IOError, OSError) as err:
            print_error("%s: %s" % (_("reset error"), err))
            raise SystemExit(1)
    finally:
        if server is not None:
            server.shutdown()

    _exec_args([ACTIVATOR_EXEC, "repo", "sync"])

elif main_cmd == "log":
    if options:
        avail_repos = _get_available_repositories()
        if options[0] in avail_repos:
            os.environ['ETP_REPO'] = options.pop(0)

    server = None
    try:
        server = get_entropy_server()
        changelog_path = server._get_local_repository_compressed_changelog_file(
            server.repository())
        if os.path.isfile(changelog_path) and os.access(changelog_path, os.R_OK):
            proc = subprocess.Popen(
                "/bin/bzcat \"%s\" | ${PAGER:-/usr/bin/less}" % (
                    changelog_path,), shell = True)
            raise SystemExit(proc.wait())
        else:
            print_error("log is not available")
            raise SystemExit(1)
    finally:
        if server is not None:
            server.shutdown()

else:
    print_menu(help_opts)
    print_error("wrong parameters")
    raise SystemExit(1)
