from io import BytesIO
from fabric.contrib.console import confirm
from fabric.decorators import task
from fabric.operations import sudo, put
from fabdeb.os import check_os, check_sudo
from fabdeb.tools import print_green


__all__ = ('apt_update', 'apt_upgrade', 'apt_dist_upgrade', 'apt_install', 'apt_cleanup')


def get_apt_repositories_text(repos):
    os_name, os_ver = check_os()
    t = repos.get(os_name)
    if t and os_ver in t:
        return t[os_ver]
    raise RuntimeError('Repositories for "{}" version "{}" do not exist.'.format(os_name, os_ver))


def get_apt_repo_install_keys_commands(repos_install_keys_commands):
    os_name, os_ver = check_os()
    t = repos_install_keys_commands.get(os_name)
    if t and os_ver in t:
        return t[os_ver]
    return ()


def set_apt_repositories(repos, repos_install_keys_commands, subconf_name=None):
    check_sudo()
    check_os()
    print_green('INFO: Set apt repositories...')
    repositories_f = BytesIO(get_apt_repositories_text(repos).encode())
    if subconf_name:
        put(repositories_f,
            '/etc/apt/sources.list.d/{}.list'.format(subconf_name.strip()),
            mode=0o644, use_sudo=True)
    else:
        sudo('mv /etc/apt/sources.list /etc/apt/sources.list.bak', warn_only=True)
        put(repositories_f, '/etc/apt/sources.list',
            mode=0o644, use_sudo=True)
    for command in get_apt_repo_install_keys_commands(repos_install_keys_commands):
        sudo(command)
    print_green('INFO: Set apt repositories... OK')


# # # COMMANDS # # #


@task
def apt_update():
    """
    aptitude update
    """
    check_sudo()
    check_os()
    print_green('INFO: Apt update...')
    sudo('aptitude update -q')
    print_green('INFO: Apt update... OK')


@task
def apt_upgrade():
    """
    aptitude upgrade
    """
    check_sudo()
    check_os()
    print_green('INFO: APT upgrade...')
    opts = '-q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"'
    sudo('aptitude upgrade {}'.format(opts))
    print_green('INFO: APT upgrade... OK')


@task
def apt_dist_upgrade():
    """
    aptitude dist-upgrade
    """
    check_sudo()
    check_os()
    print_green('INFO: APT dist upgrade...')
    opts = '-q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"'
    sudo('aptitude dist-upgrade {}'.format(opts))
    print_green('INFO: APT dist upgrade... OK')


@task
def apt_install(pkgs, comment=None, noconfirm=False):
    """
    aptitude install ...
    """
    check_sudo()
    check_os()
    assert isinstance(pkgs, str)
    pkgs = ' '.join(pkgs.split())
    comment = ' {}'.format(comment) if comment else ''
    if not noconfirm and not confirm('Do you want to apt install {}?{}'.format(pkgs, comment)):
        return
    print_green('INFO: Apt install {}...'.format(pkgs))
    opts = '-q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"'
    sudo('aptitude install {} {}'.format(opts, pkgs))
    print_green('INFO: Apt install {}... OK'.format(pkgs))


@task
def apt_cleanup():
    """
    aptitude autoclean and clean
    """
    check_sudo()
    check_os()
    if not confirm('Do you want to apt clean up?'):
        return
    print_green('INFO: Apt clean up...')
    sudo('aptitude autoclean -q -y')
    sudo('aptitude clean -q -y')
    print_green('INFO: Apt clean up... OK')
