# mypy: allow-untyped-defs

import argparse
import logging
import os
import re
import subprocess
import sys

here = os.path.abspath(os.path.dirname(__file__))
wpt_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir))

logger = logging.getLogger()


def build(tag="wpt:local", *args, **kwargs):
    subprocess.check_call(["docker",
                           "build",
                           "--pull",
                           "--tag", tag,
                           here])


def parser_push():
    parser = argparse.ArgumentParser()
    parser.add_argument("--tag", action="store",
                        help="Tag to use (default is taken from .taskcluster.yml)")
    parser.add_argument("--force", action="store_true",
                        help="Ignore warnings and push anyway")
    return parser


def walk_yaml(root, target):
    rv = []
    if isinstance(root, list):
        for value in root:
            if isinstance(value, (dict, list)):
                rv.extend(walk_yaml(value, target))
    elif isinstance(root, dict):
        for key, value in root.items():
            if isinstance(value, (dict, list)):
                rv.extend(walk_yaml(value, target))
            elif key == target:
                rv.append(value)
    return rv


def read_image_name():
    import yaml
    with open(os.path.join(wpt_root, ".taskcluster.yml")) as f:
        taskcluster_data = yaml.safe_load(f)
    taskcluster_values = set(walk_yaml(taskcluster_data, "image"))
    with open(os.path.join(wpt_root, "tools", "ci", "tc", "tasks", "test.yml")) as f:
        test_data = yaml.safe_load(f)
    tests_value = test_data["components"]["wpt-base"]["image"]
    return taskcluster_values, tests_value


def lookup_tag(tag):
    import requests
    org, repo_version = tag.split("/", 1)
    repo, version = repo_version.rsplit(":", 1)
    resp = requests.get("https://hub.docker.com/v2/repositories/%s/%s/tags/%s" %
                        (org, repo, version))
    if resp.status_code == 200:
        return True
    if resp.status_code == 404:
        return False
    resp.raise_for_status()


def push(venv, tag=None, force=False, *args, **kwargs):
    taskcluster_tags, tests_tag = read_image_name()

    taskcluster_tag = taskcluster_tags.pop()

    error_log = logger.warning if force else logger.error
    if len(taskcluster_tags) != 0 or tests_tag != taskcluster_tag:
        error_log("Image names in .taskcluster.yml and tools/ci/tc/tasks/test.yml "
                  "don't match.")
        if not force:
            sys.exit(1)
    if tag is not None and tag != taskcluster_tag:
        error_log("Supplied tag doesn't match .taskcluster.yml or "
                  "tools/ci/tc/tasks/test.yml; remember to update before pushing")
        if not force:
            sys.exit(1)
    if tag is None:
        logger.info("Using tag %s from .taskcluster.yml" % taskcluster_tag)
        tag = taskcluster_tag

    tag_re = re.compile(r"webplatformtests/wpt:\d\.\d+")
    if not tag_re.match(tag):
        error_log("Tag doesn't match expected format webplatformtests/wpt:0.x")
        if not force:
            sys.exit(1)

    if lookup_tag(tag):
        # No override for this case
        logger.critical("Tag %s already exists" % tag)
        sys.exit(1)

    build(tag)
    subprocess.check_call(["docker",
                           "push",
                           tag])


def parser_run():
    parser = argparse.ArgumentParser()
    parser.add_argument("--rebuild", action="store_true", help="Force rebuild of image")
    parser.add_argument("--checkout", action="store",
                        help="Revision to checkout in the image. "
                        "If this is not supplied we mount the wpt checkout on the host as "
                        "/home/test/web-platform-tests/")
    parser.add_argument("--privileged", action="store_true",
                        help="Run the image in priviledged mode (required for emulators)")
    parser.add_argument("--tag", action="store", default="wpt:local",
                        help="Docker image tag to use (default wpt:local)")
    return parser


def run(*args, **kwargs):
    if kwargs["rebuild"]:
        build()

    args = ["docker", "run"]
    args.extend(["--security-opt", "seccomp:%s" %
                 os.path.join(wpt_root, "tools", "docker", "seccomp.json")])
    if kwargs["privileged"]:
        args.append("--privileged")
    if kwargs["checkout"]:
        args.extend(["--env", "REF==%s" % kwargs["checkout"]])
    else:
        args.extend(["--mount",
                     "type=bind,source=%s,target=/home/test/web-platform-tests" % wpt_root])
    args.extend(["-it", kwargs["tag"]])

    proc = subprocess.Popen(args)
    proc.wait()
    return proc.returncode
