"""Internal settings."""

import json
import os
import sys
from gettext import gettext as _
from typing import Dict, cast

from gi.repository import GLib

from lutris import __version__
from lutris.util.log import logger
from lutris.util.settings import SettingsIO

PROJECT = "Lutris"
VERSION = __version__
COPYRIGHT = _("(c) 2009 Lutris Team")
AUTHORS = [_("The Lutris team")]

# Paths
CONFIG_DIR = os.path.join(GLib.get_user_config_dir(), "lutris")
DATA_DIR = os.path.join(GLib.get_user_data_dir(), "lutris")
if not os.path.exists(CONFIG_DIR):
    # Set the config dir to ~/.local/share/lutris as we're deprecating ~/.config/lutris
    CONFIG_DIR = DATA_DIR
CONFIG_FILE = os.path.join(CONFIG_DIR, "lutris.conf")
sio = SettingsIO(CONFIG_FILE)

RUNNER_DIR = sio.read_setting("runner_dir") or os.path.join(DATA_DIR, "runners")
RUNTIME_DIR = sio.read_setting("runtime_dir") or os.path.join(DATA_DIR, "runtime")
CACHE_DIR = sio.read_setting("cache_dir") or os.path.join(GLib.get_user_cache_dir(), "lutris")
TMP_DIR = os.path.join(CACHE_DIR, "tmp")
GAME_CONFIG_DIR = os.path.join(CONFIG_DIR, "games")
RUNNERS_CONFIG_DIR = os.path.join(CONFIG_DIR, "runners")
WINE_DIR: str = os.path.join(RUNNER_DIR, "wine")

SHADER_CACHE_DIR = os.path.join(CACHE_DIR, "shaders")
INSTALLER_CACHE_DIR = os.path.join(CACHE_DIR, "installer")
BANNER_PATH = os.path.join(DATA_DIR, "banners")
COVERART_PATH = os.path.join(DATA_DIR, "coverart")

RUNTIME_VERSIONS_PATH = os.path.join(CACHE_DIR, "versions.json")
ICON_PATH = os.path.join(GLib.get_user_data_dir(), "icons", "hicolor", "128x128", "apps")

if "nosetests" in sys.argv[0] or "nose2" in sys.argv[0] or "pytest" in sys.argv[0]:
    DB_PATH = "/tmp/pga.db"
else:
    DB_PATH = sio.read_setting("pga_path") or os.path.join(DATA_DIR, "pga.db")

SITE_URL = sio.read_setting("website") or "https://lutris.net"

INSTALLER_URL = SITE_URL + "/api/installers/%s"

INSTALLER_REVISION_URL = SITE_URL + "/api/installers/game/%s/revisions/%s"
GAME_URL = SITE_URL + "/games/%s/"
RUNTIME_URL = SITE_URL + "/api/runtimes"

STEAM_API_KEY = sio.read_setting("steam_api_key") or "34C9698CEB394AB4401D65927C6B3752"
STEAM_FAMILY_INCLUDE_OWN = sio.read_setting("steam_family_include_own", default="False")

SHOW_MEDIA = os.environ.get("LUTRIS_HIDE_MEDIA") != "1" and sio.read_setting("hide_media") != "True"

DEFAULT_RESOLUTION_WIDTH = sio.read_setting("default_resolution_width", default="1280")
DEFAULT_RESOLUTION_HEIGHT = sio.read_setting("default_resolution_height", default="720")

DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"


read_setting = sio.read_setting
read_bool_setting = sio.read_bool_setting
write_setting = sio.write_setting
SETTINGS_CHANGED = sio.SETTINGS_CHANGED


def get_lutris_directory_settings(directory: str) -> Dict[str, str]:
    """Reads the 'lutris.json' file in 'directory' and returns it as
    a (new) dictionary. The file is missing, unreadable, unparseable, or not a dict,
    this returns an empty dict instead."""
    if directory:
        path = os.path.join(directory, "lutris.json")
        try:
            if os.path.isfile(path):
                with open(path, "r", encoding="utf-8") as f:
                    json_data = json.load(f)
                    if not isinstance(json_data, dict):
                        logger.error("'%s' does not contain a dict, and will be ignored.", path)
                    return cast(Dict[str, str], json_data)
        except Exception as ex:
            logger.exception("Failed to read '%s': %s", path, ex)
    return {}


def set_lutris_directory_settings(directory: str, settings: Dict[str, str], merge: bool = True) -> bool:
    """Updates the 'lutris.json' file in the 'directory' given. If it does not exist, this method creates it. By
    default, if it does exist this merges the values of settings into it, but in a shallow way - only the top level
    entries are merged, not the content any of any sub-dictionaries. If 'merge' is False, this replaces the existing
    'lutris.json', so that its settings are lost.

    This function provides no way to remove a key; you can store nulls instead if appropriate.\

    If this 'lutris.json' file can't be updated (say, if 'settings' can't be represented) then this
    logs the errors, but then returns False."""
    path = os.path.join(directory, "lutris.json")
    if merge and os.path.isfile(path):
        old_settings = get_lutris_directory_settings(directory)
        old_settings.update(settings)
        settings = old_settings

    # In case settings contains something that can't be made into JSON
    # we'll save to a temporary file and rename.
    temp_path = os.path.join(directory, "lutris.json.tmp")
    try:
        with open(temp_path, "w", encoding="utf-8") as f:
            f.write(json.dumps(settings, indent=2))
        os.rename(temp_path, path)
        return True
    except Exception as ex:
        logger.exception("Could not update '%s': %s", path, ex)
        return False
    finally:
        if os.path.isfile(temp_path):
            os.unlink(temp_path)
