#!/usr/bin/env python3

import ftplib
import json
import re
import urllib.parse
import urllib.request
from distutils.version import LooseVersion


def read_chrome_version(os, channel,
        instance = 'https://omahaproxy.appspot.com/all'):
    url = '{}?os={}&channel={}'.format(instance, os, channel)
    data = urllib.request.urlopen(url).read()
    return data.split(b'\n')[1].split(b',')[2].decode()

def read_vim_version(
        instance = 'ftp://ftp.vim.org/mirror/vim'):
    url_parse_result = urllib.parse.urlparse(instance)
    host = url_parse_result.netloc
    root = url_parse_result.path
    with ftplib.FTP(host) as ftp:
        ftp.login()
        # Find the latest major release
        ftp.cwd('{}/unix'.format(root))
        tars = ftp.nlst()
        tar_iter = filter(
            lambda x: re.match(r'^vim-[0-9]+.[0-9]+\.tar\.[a-z]z2?$', x), tars)
        ver_iter = map(
            lambda x: re.sub(r'^vim-(.+)\.tar\.[a-z]z2?$', r'\1', x), tar_iter)
        max_ver = '0'
        for ver in ver_iter:
            if LooseVersion(ver) > LooseVersion(max_ver):
                max_ver = ver
        # Find the latest patch release
        ftp.cwd('{}/patches/{}'.format(root, max_ver))
        patches = ftp.nlst()
        patch_pattern = '{}.[0-9]+'.format(max_ver).replace('.', r'\.')
        patch_iter = filter(lambda x: re.match(patch_pattern, x), patches)
        max_patch = '0'
        for patch in patch_iter:
            if LooseVersion(patch) > LooseVersion(max_patch):
                max_patch = patch
    return max_patch

def read_openssl_version(version_prefix,
        instance = 'ftp://ftp.openssl.org/source'):
    url_parse_result = urllib.parse.urlparse(instance)
    host = url_parse_result.netloc
    root = url_parse_result.path
    with ftplib.FTP(host) as ftp:
        ftp.login()
        ftp.cwd(root)
        tars = ftp.nlst()
        tar_pattern = r'^openssl-{}.*\.tar\.[a-z]z2?$'.format(version_prefix)
        tar_iter = filter(
            lambda x: re.match(tar_pattern, x), tars)
        max_tar = '0'
        for tar in tar_iter:
            if tar > max_tar:
                max_tar = tar
        ver_pattern = r'^openssl-({}.*)\.tar\.[a-z]z2?$'.format(version_prefix)
        max_ver = re.sub(ver_pattern, r'\1', max_tar)
    return max_ver


def read_rpm_spec_version(url):
    spec = urllib.request.urlopen(url).read()
    return spec.split(b'\nVersion:')[1].split()[0].decode()

def read_anitya_version(project_id,
        instance = 'https://release-monitoring.org/api'):
    url = '{}/project/{}'.format(instance, project_id)
    data = urllib.request.urlopen(url).read()
    data = json.loads(data)
    return data['version']

def read_copr_version(repo, package, chroot, raw = False, debug = False,
        instance = 'https://copr.fedorainfracloud.org/api_3'):
    if repo.startswith('g/'):
        groupname, projectname = repo.split('/')[1:]
        ownername = '@' + groupname
    else:
        ownername, projectname = repo.split('/')
    build_offset = 0
    build_limit = 10
    while True:
        if build_offset % build_limit == 0:
            builds_query = {
                'ownername': ownername,
                'projectname': projectname,
                'packagename': package,
                'order': 'id',
                'order_type': 'DESC',
                'offset': build_offset,
                'limit': build_limit}
            builds_query_encoded = urllib.parse.urlencode(builds_query)
            builds_url = '{}/build/list/?{}'.format(
                instance, builds_query_encoded)
            builds_data = urllib.request.urlopen(builds_url).read()
            builds_data = json.loads(builds_data)
        if build_offset % build_limit >= len(builds_data['items']):
            break
        build_detail = builds_data['items'][build_offset % build_limit]
        build_offset += 1
        build_package_name = build_detail['source_package']['name']
        build_package_version = build_detail['source_package']['version']
        if debug:
            print('{}'.format(build_offset), end = '\t')
            print('{}'.format(build_package_name), end = '\t')
            print('{}'.format(build_package_version), end = '\n')
        if build_package_name != package:
            continue
        for build_chroot_name in build_detail['chroots']:
            if build_chroot_name == chroot:
                pkg_version = build_package_version
                if not raw:
                    pkg_version = re.sub('\.centos', '', pkg_version)
                    pkg_version = re.sub('\.el[0-9]+$', '', pkg_version)
                    pkg_version = re.sub('\.fc[0-9]+$', '', pkg_version)
                    pkg_version = re.sub('-.*$', '', pkg_version)
                    pkg_version = re.sub('^.*:', '', pkg_version)
                return pkg_version

def write_package_status(latest, packaged, name, verbose = False):
    out_of_date = LooseVersion(packaged) < LooseVersion(latest)
    if out_of_date:
        print('Please update {} package!'.format(name))
    if out_of_date or verbose:
        print('>>> latest = {}, packaged = {}'.format(latest, packaged))
    return out_of_date