from gi.repository import Gio, GLib

from typing import Optional

from iotas import const

settings = Gio.Settings.new(const.APP_ID)

STYLE = "style-variant"
WINDOW_SIZE = "window-size"
FIRST_START = "first-start"
FONT_SIZE = "font-size"
LINE_LENGTH = "line-length"
USE_MONOSPACE_FONT = "use-monospace-font"
EDITOR_THEME = "editor-theme"
HIDE_HEADERBAR_WHEN_FULLSCREEN = "hide-editor-headerbar-when-fullscreen"
BACKUP_NOTE_EXTENSION = "backup-note-extension"
PERSIST_SIDEBAR = "persist-sidebar"
INDEX_CATEGORY_STYLE = "index-category-style"

NEXTCLOUD_ENDPOINT = "nextcloud-endpoint"
NEXTCLOUD_USERNAME = "nextcloud-username"
NEXTCLOUD_PRUNE_THRESHOLD = "nextcloud-prune-threshold"
SYNC_INTERVAL = "sync-interval"
PERFORM_FULL_SERVER_REFRESH = "perform-full-server-refresh"

SPELLING_ENABLED = "spelling-enabled"
SPELLING_LANGUAGE = "spelling-language"

SHOW_STARTUP_SECRET_SERVICE_FAILURE = "show-startup-secret-service-failure"

MARKDOWN_RENDER = "markdown-render-enabled"
MARKDOWN_SYNTAX_HIGHLIGHTING = "markdown-syntax-highlighting-enabled"
MARKDOWN_KEEP_WEBKIT_PROCESS = "markdown-keep-webkit-process"
MARKDOWN_TEX_SUPPORT = "markdown-tex-support"
MARKDOWN_USE_MONOSPACE_FONT = "markdown-use-monospace-font"
MARKDOWN_RENDER_MONOSPACE_FONT_RATIO = "markdown-render-proportional-to-monospace-font-ratio"
MARKDOWN_DEFAULT_TO_RENDER = "markdown-default-to-render"

LAST_LAUNCHED_VERSION = "last-launched-version"
SHOW_EXTENDED_PREFERENCES = "show-extended-preferences"


def get_window_size() -> GLib.Variant:
    """Get window size.

    :return: The size
    :rtype: GLib.Variant
    """
    return settings.get_value(WINDOW_SIZE)


def set_window_size(width: int, height: int) -> None:
    """Set window size.

    :param int width: Width
    :param int height: Height
    """
    g_variant = GLib.Variant("ai", (width, height))
    settings.set_value(WINDOW_SIZE, g_variant)


def get_first_start() -> bool:
    """Get whether doing first startup.

    :return: First startup
    :rtype: bool
    """
    return settings.get_value(FIRST_START)


def set_first_start(value: bool) -> None:
    """Set whether first start.

    :param bool value: New value
    """
    settings.set_boolean(FIRST_START, value)


def get_use_monospace_font() -> bool:
    """Get whether to use a monospace font.

    :return: Using monospace font
    :rtype: bool
    """
    return settings.get_value(USE_MONOSPACE_FONT)


def set_use_monospace_font(value: bool) -> None:
    """Set whether to use a monospace font.

    :param bool value: New value
    """
    settings.set_boolean(USE_MONOSPACE_FONT, value)


def get_font_size() -> int:
    """Get font size.

    :return: Size
    :rtype: int
    """
    return settings.get_int(FONT_SIZE)


def set_font_size(value: int) -> None:
    """Set font size.

    :param int value: New value
    """
    settings.set_int(FONT_SIZE, value)


def get_default_font_size() -> int:
    """Get default font size.

    :return: Default size
    :rtype: int
    """
    return settings.get_default_value(FONT_SIZE).get_int32()


def get_line_length() -> int:
    """Get line length.

    :return: Size in pixels
    :rtype: int
    """
    return settings.get_int(LINE_LENGTH)


def set_line_length(value: int) -> None:
    """Set line length.

    :param int value: New value
    """
    settings.set_int(LINE_LENGTH, value)


def get_spelling_enabled() -> bool:
    """Get whether spelling enabled.

    :return: Spelling enabled
    :rtype: bool
    """
    return settings.get_value(SPELLING_ENABLED)


def set_spelling_enabled(value: bool) -> None:
    """Set spelling enabled.

    :param bool value: New value
    """
    settings.set_boolean(SPELLING_ENABLED, value)


def get_spelling_language() -> Optional[str]:
    """Get spelling language.

    :return Language tag or None if empty
    :rtype: str
    """
    lang = settings.get_string(SPELLING_LANGUAGE)
    if lang.strip() == "":
        lang = None
    return lang


def set_spelling_language(value: str) -> None:
    """Set spelling language.

    :param str value: New value
    """
    settings.set_string(SPELLING_LANGUAGE, value)


def get_style() -> str:
    """Get style.

    :return: Style
    :rtype: str
    """
    return settings.get_string(STYLE)


def set_style(value: str) -> None:
    """Set style.

    :param str value: New value
    """
    settings.set_string(STYLE, value)


def get_sync_interval() -> int:
    """Get sync interval.

    :return: Interval
    :rtype: int
    """
    return settings.get_int(SYNC_INTERVAL)


def set_sync_interval(value: int) -> None:
    """Set sync interval.

    :param int value: New value
    """
    settings.set_int(SYNC_INTERVAL, value)


def get_perform_full_server_refresh() -> bool:
    """Get whether to perform a full server refresh.

    :return: Whether to refresh
    :rtype: bool
    """
    return settings.get_value(PERFORM_FULL_SERVER_REFRESH)


def set_perform_full_server_refresh(value: bool) -> None:
    """Set whether to perform a full server refresh.

    :param bool value: New value
    """
    settings.set_boolean(PERFORM_FULL_SERVER_REFRESH, value)


def get_index_category_style() -> str:
    """Get the index category label style.

    :return: The style
    :rtype: str
    """
    return settings.get_string(INDEX_CATEGORY_STYLE)


def set_index_category_style(value: str) -> None:
    """Set the index category style.

    :param str value: New value
    """
    settings.set_string(INDEX_CATEGORY_STYLE, value)


def get_persist_sidebar() -> bool:
    """Get whether to persist the index sidebar (in large windows).

    :return: Whether to hide
    :rtype: bool
    """
    return settings.get_value(PERSIST_SIDEBAR)


def set_persist_sidebar(value: bool) -> None:
    """Set whether to persist the index sidebar (in large windows).

    :param bool value: New value
    """
    settings.set_boolean(PERSIST_SIDEBAR, value)


def get_editor_theme() -> str:
    """Get editor theme.

    :return: Theme
    :rtype: str
    """
    return settings.get_string(EDITOR_THEME)


def set_editor_theme(value: str) -> None:
    """Set editor theme.

    :param str value: New value
    """
    settings.set_string(EDITOR_THEME, value)


def get_hide_editor_headerbar_when_fullscreen() -> bool:
    """Get whether to hide the editor headerbar when fullscreen.

    :return: Whether to hide
    :rtype: bool
    """
    return settings.get_value(HIDE_HEADERBAR_WHEN_FULLSCREEN)


def set_hide_editor_headerbar_when_fullscreen(value: bool) -> None:
    """Set whether to hide the editor headerbar when fullscreen.

    :param bool value: New value
    """
    settings.set_boolean(HIDE_HEADERBAR_WHEN_FULLSCREEN, value)


def get_markdown_render_enabled() -> bool:
    """Get markdown render is enabled.

    :return: Markdown render enabled
    :rtype: bool
    """
    return settings.get_value(MARKDOWN_RENDER)


def set_markdown_render_enabled(value: bool) -> None:
    """Set markdown render enabled.

    :param bool value: New value
    """
    settings.set_boolean(MARKDOWN_RENDER, value)


def get_markdown_syntax_hightlighting_enabled() -> bool:
    """Get markdown syntax highlighting is enabled.

    :return: Highlighting enabled
    :rtype: bool
    """
    return settings.get_value(MARKDOWN_SYNTAX_HIGHLIGHTING)


def set_markdown_syntax_hightlighting_enabled(value: bool) -> None:
    """Set markdown syntax highlighting enabled.

    :param bool value: New value
    """
    settings.set_boolean(MARKDOWN_SYNTAX_HIGHLIGHTING, value)


def get_markdown_keep_webkit_process() -> bool:
    """Get markdown WebKit process being retained.

    :return: WebKit process being retained
    :rtype: bool
    """
    return settings.get_value(MARKDOWN_KEEP_WEBKIT_PROCESS)


def set_markdown_keep_webkit_process(value: bool) -> None:
    """Set markdown WebKit process being retained.

    :param bool value: New value
    """
    settings.set_boolean(MARKDOWN_KEEP_WEBKIT_PROCESS, value)


def get_markdown_tex_support() -> bool:
    """Get whether markdown TeX rendering is supported.

    :return: Markdown TeX supported
    :rtype: bool
    """
    return settings.get_value(MARKDOWN_TEX_SUPPORT)


def set_markdown_tex_support(value: bool) -> None:
    """Set whether markdown TeX rendering is supported.

    :param bool value: New value
    """
    settings.set_boolean(MARKDOWN_TEX_SUPPORT, value)


def get_markdown_use_monospace_font() -> bool:
    """Get whether to use a monospace font for the markdown render.

    :return: Using monospace font
    :rtype: bool
    """
    return settings.get_value(MARKDOWN_USE_MONOSPACE_FONT)


def set_markdown_use_monospace_font(value: bool) -> None:
    """Set whether to use a monospace font for the markdown render.

    :param bool value: New value
    """
    settings.set_boolean(MARKDOWN_USE_MONOSPACE_FONT, value)


def set_markdown_render_monospace_font_ratio(value: float) -> None:
    """Set the adjustment in size from proportional to fixed width font.

    :param bool value: New value
    """
    settings.set_double(MARKDOWN_RENDER_MONOSPACE_FONT_RATIO, value)


def get_markdown_render_monospace_font_ratio() -> float:
    """Get the adjustment in size from proportional to fixed width font.

    :return: Ratio
    :rtype: float
    """
    return settings.get_double(MARKDOWN_RENDER_MONOSPACE_FONT_RATIO)


def get_markdown_default_to_render() -> bool:
    """Get whether to render the markdown when opening the note.

    :return: Defaulting to render
    :rtype: bool
    """
    return settings.get_value(MARKDOWN_DEFAULT_TO_RENDER)


def set_markdown_default_to_render(value: bool) -> None:
    """Set whether to render the markdown when opening the note.

    :param bool value: New value
    """
    settings.set_boolean(MARKDOWN_DEFAULT_TO_RENDER, value)


def get_nextcloud_endpoint() -> str:
    """Get Nextcloud endpoint.

    :return: Endpoint
    :rtype: str
    """
    return settings.get_string(NEXTCLOUD_ENDPOINT)


def set_nextcloud_endpoint(value: str) -> None:
    """Set Nextcloud endpoint.

    :param str value: New value
    """
    settings.set_string(NEXTCLOUD_ENDPOINT, value)


def get_nextcloud_username() -> str:
    """Get Nextcloud username.

    :return: Username
    :rtype: str
    """
    return settings.get_string(NEXTCLOUD_USERNAME)


def set_nextcloud_username(value: str) -> None:
    """Set Nextcloud username.

    :param str value: New value
    """
    settings.set_string(NEXTCLOUD_USERNAME, value)


def nextcloud_sync_configured() -> bool:
    """Get whether sync with Nextcloud is configured.

    This does not mean authentication has been successful this session.

    :return: Whether configured
    :rtype: bool
    """
    sync_username = get_nextcloud_username()
    sync_endpoint = get_nextcloud_endpoint()
    return sync_username != "" and sync_endpoint != ""


def get_nextcloud_prune_threshold() -> int:
    """Get Nextcloud prune threshold.

    :return: Threshold
    :rtype: int
    """
    return settings.get_int(NEXTCLOUD_PRUNE_THRESHOLD)


def set_nextcloud_prune_threshold(value: int) -> None:
    """Set Nextcloud prune threshold.

    :param int value: New value
    """
    settings.set_int(NEXTCLOUD_PRUNE_THRESHOLD, value)


def get_show_startup_secret_service_failure() -> bool:
    """Get to show Secret Service failure at startup.

    :return: Whether to show
    :rtype: bool
    """
    return settings.get_value(SHOW_STARTUP_SECRET_SERVICE_FAILURE)


def get_backup_note_extension() -> str:
    """Get file extension for backed up notes.

    :return: Extension
    :rtype: str
    """
    return settings.get_string(BACKUP_NOTE_EXTENSION)


def set_backup_note_extension(value: str) -> None:
    """Set file extension for backed up notes.

    :param str value: New value
    """
    settings.set_string(BACKUP_NOTE_EXTENSION, value)


def get_last_launched_version() -> str:
    """Get the last version which was run.

    :return: Version
    :rtype: str
    """
    return settings.get_string(LAST_LAUNCHED_VERSION)


def set_last_launched_version(value: str) -> None:
    """Set the last version which was run.

    :param str value: New value
    """
    settings.set_string(LAST_LAUNCHED_VERSION, value)


def get_show_extended_preferences() -> bool:
    """Get whether to show a great many preferences.

    :return: Whether to show
    :rtype: bool
    """
    return settings.get_value(SHOW_EXTENDED_PREFERENCES)


def set_show_extended_preferences(value: bool) -> None:
    """Set whether to show a great many preferences.

    :param bool value: New value
    """
    settings.set_boolean(SHOW_EXTENDED_PREFERENCES, value)
