import os

from lutris.util.log import logger
from lutris.util.ubisoft.consts import UBISOFT_REGISTRY_LAUNCHER_INSTALLS
from lutris.util.wine.registry import WineRegistry

NOT_INSTALLED = "NOT_INSTALLED"
INSTALLED = "INSTALLED"


def _get_registry_value_from_path(registry_path, key):
    registry = WineRegistry()
    return registry.query(registry_path, key)


def _return_local_game_path_from_special_registry(special_registry_path):
    if not special_registry_path:
        return NOT_INSTALLED
    return _get_registry_value_from_path("HKEY_LOCAL_MACHINE" + special_registry_path, "InstallLocation")


def _return_local_game_path(launch_id):
    installs_path = UBISOFT_REGISTRY_LAUNCHER_INSTALLS
    registry = WineRegistry()
    game_path = registry.query("HKEY_LOCAL_MACHINE" + installs_path + f"\\{launch_id}", "InstallDir")
    return os.path.normcase(os.path.normpath(game_path))


def get_local_game_path(special_registry_path, launch_id):
    local_game_path = _return_local_game_path(launch_id)
    if not local_game_path and special_registry_path:
        local_game_path = _return_local_game_path_from_special_registry(special_registry_path)
    return local_game_path


async def get_size_at_path(start_path):
    total_size = 0
    for dirpath, _dirnames, filenames in os.walk(start_path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            if not os.path.islink(fp):
                total_size += os.path.getsize(fp)
    return total_size


def _is_file_at_path(path, file):
    if os.path.isdir(path):
        return os.path.isfile(os.path.join(path, file))
    return False


def _read_status_from_state_file(game_path):
    try:
        if os.path.exists(os.path.join(game_path, "uplay_install.state")):
            with open(os.path.join(game_path, "uplay_install.state"), "rb") as f:
                if f.read()[0] == 0x0A:
                    return INSTALLED
                return NOT_INSTALLED
        return NOT_INSTALLED
    except Exception as e:
        logger.warning("Issue reading install state file for %s: %s", game_path, repr(e))
        return NOT_INSTALLED


def get_game_installed_status(path, exe=None, special_registry_path=None):
    status = NOT_INSTALLED
    try:
        if path and os.access(path, os.F_OK):
            status = _read_status_from_state_file(path)
            # Fallback for old games
            if status == NOT_INSTALLED and exe and special_registry_path:
                if _is_file_at_path(path, exe):
                    status = INSTALLED
    except Exception as e:
        logger.error("Error reading game installed status at %s, %s", path, repr(e))
    return status


def get_ubisoft_registry(prefix, fullpath):
    """Get a value from the registry in a Ubisoft Connect prefix"""
    if not fullpath:
        return ""
    if fullpath.startswith("HKEY"):
        path, key = fullpath.rsplit("\\", maxsplit=1)
        path = convert_ubisoft_key(path)
        return prefix.get_registry_key(path, key)
    return fullpath


def convert_ubisoft_key(key_path):
    """Convert Ubisoft registry keys for Wine compatibility"""
    if "LOCAL_MACHINE" in key_path:
        key_path = key_path.replace("SOFTWARE\\", "Software\\Wow6432Node\\")
    key_path = key_path.replace("\\UBISOFT", "\\Ubisoft")
    key_path = key_path.replace("\\", "/")
    return key_path
