#!/usr/bin/python3

import argparse
import json
from operator import attrgetter
import re
import sys

from collections import namedtuple
from dnf.base import Base


HciRepo = namedtuple('HciRepo', ('name', 'distro', 'version', 'revision', 'packages'))


CPE = 'cpe:/o:virtuozzohci:vz:2'


def first(iterable, default=None):
    return next(iter(iterable), default)


def parse_version(version):
    # returns version in list format, i.e. [3, 5, 0, 286]
    m = re.match("^(?:[a-z0-9-]+-)?(\d+)\.(\d+)\.(\d+) \((\d+)\)$", version)
    if not m:
        # VSTOR-36790 W/A while VSTOR-36001 is not implemented
        return []
        #raise Exception('Unknown version format: %s' % version)
    return tuple(map(int, m.groups()))


def format_version(version):
    # VSTOR-36790 W/A while VSTOR-36001 is not implemented
    if not version:
        return ''
    return '{}.{}.{}-{}'.format(*version)


def get_repo_info(base, repo_id):
    repo = base.repos.get(repo_id)
    if repo is None:
        raise Exception('Repository %s is not found' % repo_id)

    tags = repo._repo.getDistroTags()
    ver = dict(tags).get(CPE)

    if not ver:
        raise Exception('Repository %s does not have required cpeid' % repo_id)

    return HciRepo(
        name=repo_id,
        revision=repo._repo.getRevision(),
        distro='%s,%s' % (CPE, ver),
        version=parse_version(ver),
        packages=base.sack.query().filterm(reponame=repo_id)
    )


def get_repos_info(repos, reposdir=None, cachedir=None, cache=None):
    base = Base()
    base.conf.errorlevel = 0
    base.conf.debuglevel = 0
    if reposdir:
        base.conf.reposdir = reposdir
    if cachedir:
        base.conf.cachedir = cachedir
    base.setup_loggers()

    base.read_all_repos()
    if not cache:
        for repo_id, repo in base.repos.items():
            if repo_id in repos:
                repo._repo.expire()

    base.fill_sack()

    repos_info = sorted((get_repo_info(base, i) for i in repos),
                        key=attrgetter('version'), reverse=True)
    max_repo = first(repos_info)
    return dict(
        version=format_version(max_repo.version),
        distro=max_repo.distro,
        repos=list(
            dict(
                repo_id=i.name,
                revision=i.revision,
                version=format_version(i.version),
                packages=list(
                    dict(
                        name=p.name,
                        version=f'{p.version}-{p.release}'
                    ) for p in i.packages
                )
            ) for i in repos_info
        ),
    )


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('repo_id')
    parser.add_argument('--reposdir')
    parser.add_argument("--cachedir")
    parser.add_argument('--cache', action='store_true')
    args = parser.parse_args()

    try:
        repos_info = get_repos_info(args.repo_id.split(','),
                                    reposdir=args.reposdir,
                                    cachedir=args.cachedir,
                                    cache=args.cache)
    except Exception as exc:
        print(str(exc))
        sys.exit(1)

    print(json.dumps(repos_info, sort_keys=True))
