#!/usr/bin/env python3

import json
import re
import sys
import urllib.request

import yaml

from tortoisehg.util import hgversion


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


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


def gen_install_apt_dependencies(extra=[]):
    return [
        'apt-get update',
        'apt-get -y install '
        + ' '.join(
            ['python3-pyqt5', 'python3-pyqt5.qsci'] + extra
        ),
    ]


def gen_update_to_mercurial_rev(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(hgver, prebuilt_images):
    if f'hg-{hgver}' in prebuilt_images:
        build = []
    else:
        build = gen_update_to_mercurial_rev(hgver) + [
            'make -C /ci/repos/mercurial local PYTHON=python3',
        ]
    return build + ['/ci/repos/mercurial/hg version --debug']


def thg_make_command(target):
    return f'make {target} PYTHON=python3 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', hgver): {
            'image': docker_image_name(hgver, prebuilt_images),
            'script': [
                *gen_install_apt_dependencies(extra=['xvfb']),
                f'pip3 install --user nose mock',
                *gen_ensure_mercurial_build(hgver, prebuilt_images),
                thg_make_command('local'),
                'xvfb-run ' + thg_make_command('tests'),
            ],
            'allow_failure': hgver == 'default',
        }
        for hgver in hg_releases + ['stable', 'default']
    }
    pytype = {
        job_name('pytype', hgver): {
            'image': docker_image_name(hgver, prebuilt_images),
            'script': [
                *gen_install_apt_dependencies(),
                # Newer versions of libcst require rustc, so the docker images
                # need to be updated to use a newer version of it.
                'pip3 install --user --upgrade libcst==0.3.20 pytype==2022.03.29',
                *gen_update_to_mercurial_rev(hgver),
                thg_make_command('local'),
                # 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'),
            ],
            '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()
