#!/usr/bin/env python3

import json
import re
import sys
import urllib.request

import yaml

from tortoisehg.util import hgversion


def job_name(name, pyver, hgver):
    return f'{name}-py{pyver}-hg-{hgver}'


def docker_image_name(pyver, hgver, prebuilt_images):
    if f'hg-{hgver}' in prebuilt_images:
        suffix = f':hg-{hgver}'
    else:
        suffix = ''
    return f'registry.heptapod.net/mercurial/ci-images/py{pyver}-hgext3rd' + suffix


def gen_install_apt_dependencies(pyver, extra=[]):
    if pyver == 2:
        python_prefix = 'python'
    elif pyver == 3:
        python_prefix = 'python3'
    return [
        'apt-get update',
        'apt-get -y install '
        + ' '.join(
            [f'{python_prefix}-pyqt5', f'{python_prefix}-pyqt5.qsci'] + extra
        ),
    ]


def gen_update_to_mercurial_rev(pyver, hgver):
    if hgver in ['stable', 'default']:
        update_to = hgver
    else:
        update_to = f"""'tag("re:\A{re.escape(hgver)}")'"""
    return [
        'hg -R /ci/repos/mercurial pull',
        f'hg -R /ci/repos/mercurial update {update_to}',
        'hg -R /ci/repos/mercurial summary',
    ]


def gen_ensure_mercurial_build(pyver, hgver, prebuilt_images):
    if f'hg-{hgver}' in prebuilt_images:
        build = []
    else:
        build = gen_update_to_mercurial_rev(pyver, hgver) + [
            f'make -C /ci/repos/mercurial local PYTHON=python{pyver}',
        ]
    return build + ['/ci/repos/mercurial/hg version --debug']


def thg_make_command(target, pyver):
    return f'make {target} PYTHON=python{pyver} HGPATH=/ci/repos/mercurial'


def gen_gitlab_ci_yml():
    # This was querying https://index.docker.io/v1/repositories/octobus/ci-py3-hgext3rd/tags,
    # which hasn't been maintained.
    prebuilt_images = ['latest']

    hg_releases = []
    for hgver in hgversion.testedwith.decode().split():
        try:
            with urllib.request.urlopen(
                f'https://www.mercurial-scm.org/repo/hg/file/{hgver}rc0'
            ):
                pass
        except urllib.error.HTTPError:
            pass
        else:
            hg_releases.append(hgver)

    tests = {
        job_name('tests', pyver, hgver): {
            'image': docker_image_name(pyver, hgver, prebuilt_images),
            'script': [
                *gen_install_apt_dependencies(pyver, extra=['xvfb']),
                f'pip{pyver} install --user nose mock',
                *gen_ensure_mercurial_build(pyver, hgver, prebuilt_images),
                thg_make_command('local', pyver),
                'xvfb-run ' + thg_make_command('tests', pyver),
            ],
            'allow_failure': hgver == 'default',
        }
        for pyver in [2, 3]
        for hgver in hg_releases + ['stable', 'default']
    }
    pytype = {
        job_name('pytype', 3, hgver): {
            'image': docker_image_name(3, hgver, prebuilt_images),
            'script': [
                *gen_install_apt_dependencies(3),
                f'pip3 install --user --upgrade pytype',
                *gen_update_to_mercurial_rev(3, hgver),
                thg_make_command('local', 3),
                # The following is a workaround for pytype's lack of support for
                # custom pyi files (https://github.com/google/pytype/issues/483).
                'ln -sf `pwd`/contrib/typehints/* '
                '`python3 -c "import pytype; '
                'print(pytype.__path__[0])"`/typeshed/stubs/',
                thg_make_command('pytype', 3),
            ],
            'allow_failure': True,
        }
        for hgver in ['stable', 'default']
    }
    return {**tests, **pytype}


if __name__ == '__main__':
    toplevel = gen_gitlab_ci_yml()
    sys.stdout.write(
        "# This file was generated by contrib/generate_gitlab_ci_yml.py.\n\n"
    )
    yaml.dump(toplevel, sys.stdout, sort_keys=False)
    sys.stdout.flush()
