"""Helper functions to assist downloading files from ModDB"""

import importlib
import re
import types

from lutris.util.log import logger

MODDB_FQDN = "https://www.moddb.com"
MODDB_URL_MATCHER = r"^https://(www\.)?moddb\.com"
MODDB_MIRROR_URL_MATCHER = r"^https://(www\.)?moddb\.com/downloads/mirror"


def is_moddb_url(url):
    return re.match(MODDB_URL_MATCHER, url.lower()) is not None


def _try_import_moddb_library():
    try:
        lib = importlib.import_module("moddb")
        return lib
    except ImportError:
        # no logging works here for some reason
        return None


class ModDB:
    def __init__(
        self, moddb_lib: types.ModuleType = _try_import_moddb_library(), parse_page_method: types.MethodType = None
    ):
        if moddb_lib is None:
            logger.warning(
                "The moddb library is not available, though the installer"
                " is attempting to install a file hosted on moddb.com. The"
                " moddb.com URLs will not be transformed, and rather passed as-is."
            )
        self.moddb_lib = moddb_lib
        self.parse = parse_page_method
        if self.parse is None and self.moddb_lib is not None:
            self.parse = self.moddb_lib.parse_page

    def transform_url(self, moddb_permalink_url):
        # no-op in case the lib did not load
        if self.moddb_lib is None:
            return moddb_permalink_url
        if not is_moddb_url(moddb_permalink_url):
            raise RuntimeError("Provided URL must be from moddb.com")

        return (
            MODDB_FQDN
            + self._autoselect_moddb_mirror(self._get_html_and_resolve_mirrors_list(moddb_permalink_url))._url
        )

    def _autoselect_moddb_mirror(self, mirrors_list):
        # dumb autoselect for now: rank mirrors by capacity (lower is better), pick first (lowest load)
        return sorted(mirrors_list, key=lambda m: m.capacity)[0]

    def _get_html_and_resolve_mirrors_list(self, moddb_permalink_url):
        # make sure the url is not that of a mirrored file
        # if this isn't checked, the helper might hang
        # while downloading a file instead of a web page
        # with no obvious reason to the user as to why
        if self._is_moddb_mirror_url(moddb_permalink_url):
            raise RuntimeError(
                "Provided URL points directly to a moddb.com mirror."
                " This is an incorrect configuration, please refer to"
                " installers.rst for details."
            )

        moddb_obj = self.parse(moddb_permalink_url)
        if not isinstance(moddb_obj, self.moddb_lib.pages.File):
            raise RuntimeError("Provided URL does not point to the page of a file hosted on moddb.com")

        mirrors_list = moddb_obj.get_mirrors()
        if not any(mirrors_list):
            raise RuntimeError("No available mirror was available for the file hosted on moddb.com")

        return mirrors_list

    def _is_moddb_mirror_url(self, url):
        return re.match(MODDB_MIRROR_URL_MATCHER, url.lower()) is not None
