import os
import requests

from subprocess import (
    check_call,
    check_output
)

from charmhelpers.core import host

from charms.reactive import (
    when,
    when_not,
    set_state,
    remove_state,
    endpoint_from_flag,
    hook,
)

from charmhelpers.fetch import (
    apt_install,
    apt_update,
    apt_purge,
    apt_autoremove,
    import_key
)

from charmhelpers.core.hookenv import (
    resource_get
)

from charms.layer import status


KATA_PACKAGES = [
    'kata-runtime',
    'kata-proxy',
    'kata-shim'
]


@when_not('kata.installed')
@when_not('endpoint.untrusted.departed')
def install_kata():
    """
    Install the Kata container runtime.

    :returns: None
    """
    dist = host.lsb_release()
    release = '{}_{}'.format(
        dist['DISTRIB_ID'],
        dist['DISTRIB_RELEASE']
    )

    arch = check_output(['arch']).decode().strip()

    archive = resource_get('kata-archive')

    if not archive or os.path.getsize(archive) == 0:
        status.maintenance('Installing Kata via apt')
        gpg_key = requests.get(
            'http://download.opensuse.org/repositories/home:/katacontainers:/'
            'releases:/{}:/master/x{}/Release.key'.format(arch, release)).text
        import_key(gpg_key)

        with open('/etc/apt/sources.list.d/kata-containers.list', 'w') as f:
            f.write(
                'deb http://download.opensuse.org/repositories/home:/'
                'katacontainers:/releases:/{}:/master/x{}/ /'
                .format(arch, release)
            )

        apt_update()
        apt_install(KATA_PACKAGES)

    else:
        status.maintenance('Installing Kata via resource')
        unpack = '/tmp/kata-debs'

        if not os.path.isdir(unpack):
            os.makedirs(unpack, exist_ok=True)

        check_call(['tar', '-xvf', archive, '-C', unpack])
        check_call('apt-get install -y {}/*.deb'.format(unpack), shell=True)

    status.active('Kata runtime available')
    set_state('kata.installed')


@when('endpoint.untrusted.departed')
def purge_kata():
    """
    Purge Kata containers.

    :return: None
    """
    status.maintenance('Purging Kata')

    apt_purge(KATA_PACKAGES, fatal=False)

    source = '/etc/apt/sources.list.d/kata-containers.list'
    if os.path.isfile(source):
        os.remove(source)

    apt_autoremove()

    remove_state('kata.installed')


@when('kata.installed')
@when('endpoint.untrusted.joined')
@when_not('endpoint.untrusted.departed')
def publish_config():
    """
    Pass configuration over the interface.

    :return: None
    """
    endpoint = endpoint_from_flag('endpoint.untrusted.joined')
    endpoint.set_config(
        name='kata',
        binary_path='/usr/bin/kata-runtime'
    )


@hook('pre-series-upgrade')
def pre_series_upgrade():
    """Set status during series upgrade."""
    status.blocked('Series upgrade in progress')


@hook('post-series-upgrade')
def post_series_upgrade():
    """Reset status to active after series upgrade."""
    status.active('Kata runtime available')
