import sys

from .utils import MirrorException

# Disable tqdm if present
try:
    from tqdm import tqdm

    tqdm._old__init__ = tqdm.__init__

    def _new_init(self, *args, **kwargs):
        kwargs["disable"] = True
        self._old__init__(*args, **kwargs)

    tqdm.__init__ = _new_init
except ImportError:
    pass


SUBDIR_MAP = {
    "osx-32": ("osx", "x86"),
    "osx-64": ("osx", "x86_64"),
    "win-32": ("win", "x86"),
    "win-64": ("win", "x86_64"),
    "win-arm64": ("win", "arm64"),
    "linux-32": ("linux", "x86"),
    "linux-64": ("linux", "x86_64"),
    "linux-aarch64": ("linux", "aarch64"),
    "linux-armv6l": ("linux", "armv6l"),
    "linux-armv7l": ("linux", "armv7l"),
    "linux-ppc64le": ("linux", "ppc64le"),
    "linux-s390x": ("linux", "s390x"),
    "noarch": (None, None),
}


def parse_subdir(subdir):
    """
    Lifted from
    https://github.com/Anaconda-Platform/anaconda-server/blob/develop/anaconda_platform/utils/__init__.py#L133-L179
    """  # noqa: E501
    plat_arch = SUBDIR_MAP.get(subdir, subdir.split("-", 1))
    if len(plat_arch) == 1:
        plat_arch.append("")
    return tuple(plat_arch)


def get_repo_api(config):
    global errors
    global inspect_conda_package
    try:
        from binstar_client.utils import get_server_api, get_config
        from binstar_client.inspect_package.conda import inspect_conda_package
        from binstar_client import errors
    except ImportError:
        raise MirrorException("Please install the 'anaconda-client' package.")
    r_config = get_config()
    dest_site = config.dest_site or r_config["default_site"]
    if dest_site in ("null", "None"):
        dest_site = next(dest_site.keys())
    kwargs = {"site": dest_site}
    if config.password:
        kwargs["token"] = config.password
    api = get_server_api(**kwargs)
    if not config.verify_ssl_dst and not api.session.verify:
        config.verify_ssl_dst = False
    api.session.verify = config.verify_ssl_mode("dst")
    config.dest_channel_alias = api.session.get(api.domain).json()["conda_url"]
    if api.domain == "https://api.anaconda.org":
        config.valid_formats = ("conda", "tarbz2")
    else:
        config.valid_formats = ("tarbz2",)
    config.can_patch = False
    api.is_public = config.access_policy != "private"
    return api


def begin_channel(api, cname, dry_run):
    try:
        api.user(cname)
    except errors.NotFound:
        raise MirrorException("Channel not found: %s" % cname)


_packages = {}


def ensure_package_exists(api, account, info, package_attrs, release_attrs, public):
    name = info["name"]
    prec = _packages.get(name)
    if prec is None:
        try:
            prec = api.package(account, name)
        except errors.NotFound:
            prec = api.add_package(
                account,
                name,
                summary=package_attrs.get("summary", None),
                attrs=package_attrs,
                public=public,
                license=info.get("license", info.get("license_family", None)),
                license_url=package_attrs.get("license_url", None),
                license_family=package_attrs.get("license_family", None),
            )
        _packages[name] = prec
    version = info["version"]
    if version in prec.setdefault("versions", []):
        return
    response = api.add_release(account, name, version, None, None, release_attrs)
    prec["versions"].append(version)
    prec.setdefault("releases", []).append(response)


def del_object(api, cname, platform, fn, metadata=None):
    response = api.remove_dist(
        cname, metadata["name"], metadata["version"], "%s/%s" % (platform, fn)
    )
    if response and response["status"] != "ok":
        raise MirrorException("%s: %s" % (response["status"], response["message"]))


def put_object(api, cname, platform, fn, path_or_data=None, metadata=None):
    info = metadata.copy()
    info["platform"], info["arch"] = parse_subdir(platform)
    try:
        package_attrs, release_attrs, file_attrs = inspect_conda_package(path_or_data)
    except Exception as exc:
        message = getattr(exc, "message", exc)
        raise MirrorException("inspect_conda_package: %s" % message)
    ensure_package_exists(api, cname, info, package_attrs, release_attrs, api.is_public)
    try:
        with open(path_or_data, "rb") as fp:
            api.upload(
                cname,
                info["name"],
                info["version"],
                "%s/%s" % (platform, fn),
                fp,
                "conda",
                description=package_attrs.get("description", None),
                attrs=info,
                dependencies=[],
            )
    except Exception as exc:
        message = getattr(exc, "message", exc)
        raise MirrorException("api.upload: %s" % message)


def main():
    from .common import main as _main

    _main(sys.modules[__name__])
