#!/usr/bin/env python

# Copyright (C) 2012, Aleksey Lim
#
# 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 3 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 os
import re
import sys
import logging
from optparse import OptionParser
from os.path import basename, join
from gettext import gettext as _

from sweets_distribution import env, optparse, printf
from sweets_distribution.pms import Pms
from sweets_distribution.util import enforce


def cmd_status():
    pms = Pms()

    printf.dump(_('Platform:    %s-%s'), pms.distro_id, pms.distro_rel)

    printf.dump('')
    plugged_repos = []
    for i in pms.plugged_repos:
        plugged_repos.append('%-10s%s-%s' % i)
    printf.dump(_('Repositories:'))
    for i in plugged_repos or [_('(none)')]:
        printf.dump('   %s' % i)

    printf.dump('')
    to_sync = []
    for package in pms.to_sync():
        to_sync.append(str(package))
    if not to_sync and pms.plugged_repos and \
            (pms.new_config or not pms.has_keys()):
        to_sync.append(_('(yes)'))
    if to_sync:
        printf.hint(_('Use "sync" command to synchronize packages'))
    printf.dump(_('Need to sync:'))
    for i in to_sync or [_('(no)')]:
        printf.dump('   %s' % i)

    printf.dump('')
    all_repos = {}
    for repo, distro_id, distro_rel in pms.fetch_repos():
        if distro_id != pms.distro_id:
            continue
        all_repos.setdefault(repo, [])
        all_repos[repo].append('%s-%s' % (distro_id, distro_rel))
    printf.dump(_('Available repositories:'))
    for repo in sorted(all_repos.keys()):
        printf.dump('   %-10s%s', repo, ', '.join(all_repos[repo]))
    if not plugged_repos and all_repos:
        printf.hint(_('Use "select" command to start using ' \
                'one of available repositories'))

    __, rel = pms.resolve_package('sweets-desktop')
    if not rel:
        printf.hint(_('Instlall "sweets-desktop" package ' \
                'to have Sweets Desktop'))


def cmd_sync():
    enforce_root()

    pms = Pms()
    to_uninstall = []
    to_install = []

    for package in pms.to_sync():
        if package.downgrade:
            to_uninstall.append(package)
        to_install.append(package)

    pms.update()
    pms.uninstall(to_uninstall)
    pms.install(to_install)


def cmd_select():
    enforce_root()
    enforce(args, _('Specify repository to select'))

    repo = args.pop(0)
    pms = Pms()

    distro_rel = pms.distro_rel
    if args:
        arg = args[0].split('-')[-1]
        if re.match('[0-9.]+$', arg):
            distro_rel = arg
            args.pop(0)

    pms.select(repo, distro_rel)

    printf.hint(_('Use "status" command for getting status after ' \
            'selecting new repository'))
    printf.hint(_('Use "sync" command to make sure that installed ' \
            'packages are the same as in newly selected repository'))


def cmd_clean():
    enforce_root()
    Pms().clean()


def cmd_install():
    enforce_root()
    Pms().self_install()
    printf.hint(_('Run "sweets-distribution -h" for getting help'))


def enforce_root():
    if os.getuid() != 0:
        printf.hint(_('Re-run command with prefixing it with "sudo" command'))
        raise RuntimeError(_('Command should be launched from the root user'))


HELP = _("""
Commands:
  select REPO [DISTRO]  register specified repository in the system
  sync                  make sure that currently installed packages
                        come from selected repository
  clean                 unregister current repository
  status                current repository status information

See http://wiki.sugarlabs.org/go/Sweets_Distribution for details.""")

parser = OptionParser(
        usage='%prog [OPTIONS]',
        description='Managing Sweets Distribution repositories.',
        add_help_option=False)
parser.add_option('-h', '--help',
        help=_('show this help message and exit'),
        action='store_true')

optparse.Option.seek('main', env)
options, args = optparse.Option.parse_args(parser, [
        '/etc/sweets.conf',
        '~/.config/sweets/config',
        join(os.environ['HOME'], '.sugar',
            os.environ.get('SUGAR_PROFILE', 'default'), 'sweets.conf'),
        ])

if not args and not options.help:
    prog = basename(sys.argv[0])
    print 'Usage: %s [OPTIONS] [COMMAND]' % prog
    print '       %s -h|--help' % prog
    print
    print parser.description
    print HELP
    exit(0)

if options.help:
    parser.print_help()
    print HELP
    exit(0)

try:
    if not env.debug.value:
        level = logging.WARNING
    elif env.debug.value == 1:
        level = logging.INFO
    else:
        level = logging.DEBUG
    logging.basicConfig(level=level,
            format='-- %(levelname)s %(message)s')

    while args:
        cmd = args.pop(0)
        enforce('cmd_' + cmd in globals(),
                _('Unknown command "%s"') % cmd)
        status = globals()['cmd_' + cmd]()
        if status:
            exit(status)

except KeyboardInterrupt:
    exit(1)
except Exception:
    printf.exception()
    exit(1)
finally:
    if not env.no_hints.value:
        printf.flush_hints()
