# coding=utf-8
import locale
import logging
import os
import platform
import traceback

import logger
import copy

from requests import HTTPError
from item_details import ItemDetailsMenu
from refresh_item import RefreshItem
from menu_helpers import add_incl_excl_options, dig_tree, set_refresh_menu_state, \
    default_thumb, debounce, ObjectContainer, SubFolderObjectContainer, route
from main import fatality, InclExclMenu
from advanced import DispatchRestart
from subzero.constants import ART, PREFIX, DEPENDENCY_MODULE_NAMES
from support.extract import season_extract_embedded
from support.scheduler import scheduler
from support.config import config
from support.helpers import timestamp, df, display_language
from support.ignore import get_decision_list
from support.items import get_all_items, get_items_info, get_item_kind_from_rating_key, get_item, get_item_title
from support.i18n import _

# init GUI
ObjectContainer.art = R(ART)
ObjectContainer.no_cache = True

# default thumb for DirectoryObjects
DirectoryObject.thumb = default_thumb
Plugin.AddViewGroup("full_details", viewMode="InfoList", mediaType="items", type="list", summary=2)


@route(PREFIX + '/section/firstLetter/key', deeper=bool)
def FirstLetterMetadataMenu(rating_key, key, title=None, base_title=None, display_items=False, previous_item_type=None,
                            previous_rating_key=None):
    """
    displays the contents of a section filtered by the first letter
    :param rating_key: actually is the section's key
    :param key: the firstLetter wanted
    :param title: the first letter, or #
    :param deeper:
    :return:
    """
    title = base_title + " > " + unicode(title)
    oc = SubFolderObjectContainer(title2=title, no_cache=True, no_history=True)

    items = get_all_items(key="first_character", value=[rating_key, key], base="library/sections", flat=False)
    kind, deeper = get_items_info(items)
    dig_tree(oc, items, MetadataMenu,
             pass_kwargs={"base_title": title, "display_items": deeper, "previous_item_type": kind,
                          "previous_rating_key": rating_key})
    return oc


@route(PREFIX + '/section/contents', display_items=bool)
def MetadataMenu(rating_key, title=None, base_title=None, display_items=False, previous_item_type=None,
                 previous_rating_key=None, message=None, header=None, randomize=None):
    """
    displays the contents of a section based on whether it has a deeper tree or not (movies->movie (item) list; series->series list)
    :param rating_key:
    :param title:
    :param base_title:
    :param display_items:
    :param previous_item_type:
    :param previous_rating_key:
    :return:
    """
    title = unicode(title)
    item_title = title
    title = base_title + " > " + title
    oc = SubFolderObjectContainer(title2=title, no_cache=True, no_history=True, header=header, message=message,
                                  view_group="full_details")

    current_kind = get_item_kind_from_rating_key(rating_key)

    if display_items:
        timeout = 30
        show = None

        # add back to series for season
        if current_kind == "season":
            timeout = 720

            show = get_item(previous_rating_key)
            oc.add(DirectoryObject(
                key=Callback(MetadataMenu, rating_key=show.rating_key, title=show.title, base_title=show.section.title,
                             previous_item_type="section", display_items=True, randomize=timestamp()),
                title=_(u"< Back to %s", show.title),
                thumb=show.thumb or default_thumb
            ))
        elif current_kind == "series":
            # it shouldn't take more than 6 minutes to scan all of a series' files and determine the force refresh
            timeout = 3600

        items = get_all_items(key="children", value=rating_key, base="library/metadata")
        kind, deeper = get_items_info(items)
        dig_tree(oc, items, MetadataMenu,
                 pass_kwargs={"base_title": title, "display_items": deeper, "previous_item_type": kind,
                              "previous_rating_key": rating_key})

        # we don't know exactly where we are here, only add ignore option to series
        if current_kind in ("series", "season"):
            item = get_item(rating_key)
            sub_title = get_item_title(item)
            add_incl_excl_options(oc, current_kind, title=sub_title, rating_key=rating_key, callback_menu=InclExclMenu)

        # mass-extract embedded
        if current_kind == "season" and config.plex_transcoder:
            for lang in config.lang_list:
                oc.add(DirectoryObject(
                    key=Callback(SeasonExtractEmbedded, rating_key=rating_key, language=lang,
                                 base_title=show.section.title, display_items=display_items, item_title=item_title,
                                 title=title,
                                 previous_item_type=previous_item_type, with_mods=True,
                                 previous_rating_key=previous_rating_key, randomize=timestamp()),
                    title=_(u"Extract missing %(language)s embedded subtitles", language=display_language(lang)),
                    summary=_("Extracts the not yet extracted embedded subtitles of all episodes for the current "
                              "season with all configured default modifications")
                ))
                oc.add(DirectoryObject(
                    key=Callback(SeasonExtractEmbedded, rating_key=rating_key, language=lang,
                                 base_title=show.section.title, display_items=display_items, item_title=item_title,
                                 title=title, force=True,
                                 previous_item_type=previous_item_type, with_mods=True,
                                 previous_rating_key=previous_rating_key, randomize=timestamp()),
                    title=_(u"Extract and activate %(language)s embedded subtitles", language=display_language(lang)),
                    summary=_("Extracts embedded subtitles of all episodes for the current season "
                              "with all configured default modifications")
                ))

        # add refresh
        oc.add(DirectoryObject(
            key=Callback(RefreshItem, rating_key=rating_key, item_title=title, refresh_kind=current_kind,
                         previous_rating_key=previous_rating_key, timeout=timeout * 1000, randomize=timestamp()),
            title=_(u"Refresh: %s", item_title),
            summary=_("Refreshes %(the_movie_series_season_episode)s, possibly searching for missing and picking up "
                      "new subtitles on disk", the_movie_series_season_episode=_(u"the %s" % current_kind))
        ))
        oc.add(DirectoryObject(
            key=Callback(RefreshItem, rating_key=rating_key, item_title=title, force=True,
                         refresh_kind=current_kind, previous_rating_key=previous_rating_key, timeout=timeout * 1000,
                         randomize=timestamp()),
            title=_(u"Auto-Find subtitles: %s", item_title),
            summary=_("Issues a forced refresh, ignoring known subtitles and searching for new ones")
        ))
    else:
        return ItemDetailsMenu(rating_key=rating_key, title=title, item_title=item_title)

    return oc


@route(PREFIX + '/season/extract_embedded/{rating_key}/{language}')
def SeasonExtractEmbedded(**kwargs):
    rating_key = kwargs.get("rating_key")
    requested_language = kwargs.pop("language")
    with_mods = kwargs.pop("with_mods")
    item_title = kwargs.pop("item_title")
    title = kwargs.pop("title")
    force = kwargs.pop("force", False)

    Thread.Create(season_extract_embedded, **{"rating_key": rating_key, "requested_language": requested_language,
                                              "with_mods": with_mods, "force": force})

    kwargs["header"] = _("Success")
    kwargs["message"] = _(u"Extracting of embedded subtitles for %s triggered", title)

    kwargs.pop("randomize")
    return MetadataMenu(randomize=timestamp(), title=item_title, **kwargs)


@route(PREFIX + '/ignore_list')
def IgnoreListMenu():
    ref_list = get_decision_list()
    include = ref_list.store == "include"
    list_title = _("Include list" if include else "Ignore list")
    oc = SubFolderObjectContainer(title2=list_title, replace_parent=True)
    for key in ref_list.key_order:
        values = ref_list[key]
        for value in values:
            add_incl_excl_options(oc, key, title=ref_list.get_title(key, value), rating_key=value,
                                  callback_menu=InclExclMenu)
    return oc


@route(PREFIX + '/history')
def HistoryMenu():
    from support.history import get_history
    history = get_history()
    oc = SubFolderObjectContainer(title2=_("History"), replace_parent=True)

    for item in history.items[:100]:
        possible_language = item.language
        language_display = item.lang_name if not possible_language else display_language(possible_language)

        oc.add(DirectoryObject(
            key=Callback(ItemDetailsMenu, title=item.title, item_title=item.item_title,
                         rating_key=item.rating_key),
            title=u"%s (%s)" % (item.item_title, _(item.mode_verbose)),
            summary=_(u"%s in %s (%s, score: %s), %s", language_display, item.section_title,
                                                       _(item.provider_name), item.score, df(item.time)),
            thumb=item.thumb or default_thumb
        ))

    history.destroy()

    return oc


@route(PREFIX + '/missing/refresh')
@debounce
def RefreshMissing(randomize=None):
    scheduler.dispatch_task("SearchAllRecentlyAddedMissing")
    header = "Refresh of recently added items with missing subtitles triggered"
    return fatality(header=header, replace_parent=True)


def replace_item(obj, key, replace_value):
    for k, v in obj.items():
        if isinstance(v, dict):
            obj[k] = replace_item(v, key, replace_value)
    if key in obj:
        obj[key] = replace_value
    return obj


def check_connections():
    # debug drone
    Log.Debug("Checking connections ...")
    log_buffer = []
    try:
        from subliminal_patch.refiners.drone import SonarrClient, RadarrClient
        log_buffer.append(["----- Connections -----"])
        for key, cls in [("sonarr", SonarrClient), ("radarr", RadarrClient)]:
            if key in config.refiner_settings:
                cname = key.capitalize()
                try:
                    status = cls(**config.refiner_settings[key]).status(timeout=5)
                except HTTPError, e:
                    if e.response.status_code == 401:
                        log_buffer.append(("%s: NOT WORKING - BAD API KEY", cname))
                    else:
                        log_buffer.append(("%s: NOT WORKING - %s", cname, traceback.format_exc()))
                except:
                    log_buffer.append(("%s: NOT WORKING - %s", cname, traceback.format_exc()))
                else:
                    if status and status["version"]:
                        log_buffer.append(("%s: OK - %s", cname, status["version"]))
                    else:
                        log_buffer.append(("%s: NOT WORKING - %s", cname))
    except:
        log_buffer.append(("Something went really wrong when evaluating Sonarr/Radarr: %s", traceback.format_exc()))
    finally:
        Core.log.setLevel(logging.DEBUG)
        for entry in log_buffer:
            Log.Debug(*entry)

        Core.log.setLevel(logging.getLevelName(Prefs["log_level"]))


@route(PREFIX + '/ValidatePrefs', enforce_route=True)
def ValidatePrefs():
    Core.log.setLevel(logging.DEBUG)

    if Prefs["log_console"]:
        Core.log.addHandler(logger.console_handler)
        Log.Debug("Logging to console from now on")
    else:
        Core.log.removeHandler(logger.console_handler)
        Log.Debug("Stop logging to console")

    # cache the channel state
    update_dict = False
    restart = False

    # reset pin
    Dict["pin_correct_time"] = None

    config.initialize()
    if "channel_enabled" not in Dict:
        update_dict = True

    elif Dict["channel_enabled"] != config.enable_channel:
        Log.Debug("Interface features %s, restarting plugin", "enabled" if config.enable_channel else "disabled")
        update_dict = True
        restart = True

    if "plugin_pin_mode2" not in Dict:
        update_dict = True

    elif Dict["plugin_pin_mode2"] != Prefs["plugin_pin_mode2"]:
        update_dict = True
        restart = True

    if update_dict:
        Dict["channel_enabled"] = config.enable_channel
        Dict["plugin_pin_mode2"] = Prefs["plugin_pin_mode2"]
        Dict.Save()

    if restart:
        scheduler.stop()
        DispatchRestart()
        return

    scheduler.setup_tasks()
    scheduler.clear_task_data("MissingSubtitles")
    set_refresh_menu_state(None)

    Log.Debug("Validate Prefs called.")

    # SZ config debug
    Log.Debug("--- SZ Config-Debug ---")
    for attr in [
            "version", "app_support_path", "data_path", "data_items_path", "enable_agent",
            "enable_channel", "permissions_ok", "missing_permissions", "fs_encoding",
            "subtitle_destination_folder", "include", "include_exclude_paths", "include_exclude_sz_files",
            "new_style_cache", "dbm_supported", "lang_list", "providers", "normal_subs", "forced_only", "forced_also",
            "plex_transcoder", "refiner_settings", "unrar", "adv_cfg_path", "use_custom_dns",
            "has_anticaptcha", "anticaptcha_cls", "mediainfo_bin"]:

        value = getattr(config, attr)
        if isinstance(value, dict):
            d = replace_item(copy.deepcopy(value), "api_key", "<KEY>")
            Log.Debug("config.%s: %s", attr, d)
            continue

        if attr in ("api_key",):
            value = "<KEY>"

        Log.Debug("config.%s: %s", attr, value)

    for attr in ["plugin_log_path", "server_log_path"]:
        value = getattr(config, attr)

        if value:
            access = os.access(value, os.R_OK)
            if Core.runtime.os == "Windows":
                try:
                    f = open(value, "r")
                    f.read(1)
                    f.close()
                except:
                    access = False

        Log.Debug("config.%s: %s (accessible: %s)", attr, value, access)

    for attr in [
            "subtitles.save.filesystem", ]:
        Log.Debug("Pref.%s: %s", attr, Prefs[attr])

    if "sonarr" in config.refiner_settings or "radarr" in config.refiner_settings:
        Thread.Create(check_connections)

    # fixme: check existance of and os access of logs
    Log.Debug("----- Environment -----")
    Log.Debug("Platform: %s", Core.runtime.platform)
    Log.Debug("OS: %s", Core.runtime.os)
    Log.Debug("Python: %s", platform.python_version())
    for key, value in os.environ.iteritems():
        if key.startswith("PLEX") or key.startswith("SZ_"):
            if "TOKEN" in key:
                outval = "xxxxxxxxxxxxxxxxxxx"

            else:
                outval = value
            Log.Debug("%s: %s", key, outval)
    Log.Debug("Locale: %s", locale.getdefaultlocale())
    Log.Debug("-----------------------")

    Log.Debug("Setting log-level to %s", Prefs["log_level"])
    logger.register_logging_handler(DEPENDENCY_MODULE_NAMES, level=Prefs["log_level"])
    Core.log.setLevel(logging.getLevelName(Prefs["log_level"]))
    os.environ['U1pfT01EQl9LRVk'] = '789CF30DAC2C8B0AF433F5C9AD34290A712DF30D7135F12D0FB3E502006FDE081E'

    return

# coding=utf-8
import locale
import logging
import os
import platform
import traceback

import logger
import copy

from requests import HTTPError
from item_details import ItemDetailsMenu
from refresh_item import RefreshItem
from menu_helpers import add_incl_excl_options, dig_tree, set_refresh_menu_state, \
    default_thumb, debounce, ObjectContainer, SubFolderObjectContainer, route
from main import fatality, InclExclMenu
from advanced import DispatchRestart
from subzero.constants import ART, PREFIX, DEPENDENCY_MODULE_NAMES
from support.extract import season_extract_embedded
from support.scheduler import scheduler
from support.config import config
from support.helpers import timestamp, df, display_language
from support.ignore import get_decision_list
from support.items import get_all_items, get_items_info, get_item_kind_from_rating_key, get_item, get_item_title
from support.i18n import _

# init GUI
ObjectContainer.art = R(ART)
ObjectContainer.no_cache = True

# default thumb for DirectoryObjects
DirectoryObject.thumb = default_thumb
Plugin.AddViewGroup("full_details", viewMode="InfoList", mediaType="items", type="list", summary=2)


@route(PREFIX + '/section/firstLetter/key', deeper=bool)
def FirstLetterMetadataMenu(rating_key, key, title=None, base_title=None, display_items=False, previous_item_type=None,
                            previous_rating_key=None):
    """
    displays the contents of a section filtered by the first letter
    :param rating_key: actually is the section's key
    :param key: the firstLetter wanted
    :param title: the first letter, or #
    :param deeper:
    :return:
    """
    title = base_title + " > " + unicode(title)
    oc = SubFolderObjectContainer(title2=title, no_cache=True, no_history=True)

    items = get_all_items(key="first_character", value=[rating_key, key], base="library/sections", flat=False)
    kind, deeper = get_items_info(items)
    dig_tree(oc, items, MetadataMenu,
             pass_kwargs={"base_title": title, "display_items": deeper, "previous_item_type": kind,
                          "previous_rating_key": rating_key})
    return oc


@route(PREFIX + '/section/contents', display_items=bool)
def MetadataMenu(rating_key, title=None, base_title=None, display_items=False, previous_item_type=None,
                 previous_rating_key=None, message=None, header=None, randomize=None):
    """
    displays the contents of a section based on whether it has a deeper tree or not (movies->movie (item) list; series->series list)
    :param rating_key:
    :param title:
    :param base_title:
    :param display_items:
    :param previous_item_type:
    :param previous_rating_key:
    :return:
    """
    title = unicode(title)
    item_title = title
    title = base_title + " > " + title
    oc = SubFolderObjectContainer(title2=title, no_cache=True, no_history=True, header=header, message=message,
                                  view_group="full_details")

    current_kind = get_item_kind_from_rating_key(rating_key)

    if display_items:
        timeout = 30
        show = None

        # add back to series for season
        if current_kind == "season":
            timeout = 720

            show = get_item(previous_rating_key)
            oc.add(DirectoryObject(
                key=Callback(MetadataMenu, rating_key=show.rating_key, title=show.title, base_title=show.section.title,
                             previous_item_type="section", display_items=True, randomize=timestamp()),
                title=_(u"< Back to %s", show.title),
                thumb=show.thumb or default_thumb
            ))
        elif current_kind == "series":
            # it shouldn't take more than 6 minutes to scan all of a series' files and determine the force refresh
            timeout = 3600

        items = get_all_items(key="children", value=rating_key, base="library/metadata")
        kind, deeper = get_items_info(items)
        dig_tree(oc, items, MetadataMenu,
                 pass_kwargs={"base_title": title, "display_items": deeper, "previous_item_type": kind,
                              "previous_rating_key": rating_key})

        # we don't know exactly where we are here, only add ignore option to series
        if current_kind in ("series", "season"):
            item = get_item(rating_key)
            sub_title = get_item_title(item)
            add_incl_excl_options(oc, current_kind, title=sub_title, rating_key=rating_key, callback_menu=InclExclMenu)

        # mass-extract embedded
        if current_kind == "season" and config.plex_transcoder:
            for lang in config.lang_list:
                oc.add(DirectoryObject(
                    key=Callback(SeasonExtractEmbedded, rating_key=rating_key, language=lang,
                                 base_title=show.section.title, display_items=display_items, item_title=item_title,
                                 title=title,
                                 previous_item_type=previous_item_type, with_mods=True,
                                 previous_rating_key=previous_rating_key, randomize=timestamp()),
                    title=_(u"Extract missing %(language)s embedded subtitles", language=display_language(lang)),
                    summary=_("Extracts the not yet extracted embedded subtitles of all episodes for the current "
                              "season with all configured default modifications")
                ))
                oc.add(DirectoryObject(
                    key=Callback(SeasonExtractEmbedded, rating_key=rating_key, language=lang,
                                 base_title=show.section.title, display_items=display_items, item_title=item_title,
                                 title=title, force=True,
                                 previous_item_type=previous_item_type, with_mods=True,
                                 previous_rating_key=previous_rating_key, randomize=timestamp()),
                    title=_(u"Extract and activate %(language)s embedded subtitles", language=display_language(lang)),
                    summary=_("Extracts embedded subtitles of all episodes for the current season "
                              "with all configured default modifications")
                ))

        # add refresh
        oc.add(DirectoryObject(
            key=Callback(RefreshItem, rating_key=rating_key, item_title=title, refresh_kind=current_kind,
                         previous_rating_key=previous_rating_key, timeout=timeout * 1000, randomize=timestamp()),
            title=_(u"Refresh: %s", item_title),
            summary=_("Refreshes %(the_movie_series_season_episode)s, possibly searching for missing and picking up "
                      "new subtitles on disk", the_movie_series_season_episode=_(u"the %s" % current_kind))
        ))
        oc.add(DirectoryObject(
            key=Callback(RefreshItem, rating_key=rating_key, item_title=title, force=True,
                         refresh_kind=current_kind, previous_rating_key=previous_rating_key, timeout=timeout * 1000,
                         randomize=timestamp()),
            title=_(u"Auto-Find subtitles: %s", item_title),
            summary=_("Issues a forced refresh, ignoring known subtitles and searching for new ones")
        ))
    else:
        return ItemDetailsMenu(rating_key=rating_key, title=title, item_title=item_title)

    return oc


@route(PREFIX + '/season/extract_embedded/{rating_key}/{language}')
def SeasonExtractEmbedded(**kwargs):
    rating_key = kwargs.get("rating_key")
    requested_language = kwargs.pop("language")
    with_mods = kwargs.pop("with_mods")
    item_title = kwargs.pop("item_title")
    title = kwargs.pop("title")
    force = kwargs.pop("force", False)

    Thread.Create(season_extract_embedded, **{"rating_key": rating_key, "requested_language": requested_language,
                                              "with_mods": with_mods, "force": force})

    kwargs["header"] = _("Success")
    kwargs["message"] = _(u"Extracting of embedded subtitles for %s triggered", title)

    kwargs.pop("randomize")
    return MetadataMenu(randomize=timestamp(), title=item_title, **kwargs)


@route(PREFIX + '/ignore_list')
def IgnoreListMenu():
    ref_list = get_decision_list()
    include = ref_list.store == "include"
    list_title = _("Include list" if include else "Ignore list")
    oc = SubFolderObjectContainer(title2=list_title, replace_parent=True)
    for key in ref_list.key_order:
        values = ref_list[key]
        for value in values:
            add_incl_excl_options(oc, key, title=ref_list.get_title(key, value), rating_key=value,
                                  callback_menu=InclExclMenu)
    return oc


@route(PREFIX + '/history')
def HistoryMenu():
    from support.history import get_history
    history = get_history()
    oc = SubFolderObjectContainer(title2=_("History"), replace_parent=True)

    for item in history.items[:100]:
        possible_language = item.language
        language_display = item.lang_name if not possible_language else display_language(possible_language)

        oc.add(DirectoryObject(
            key=Callback(ItemDetailsMenu, title=item.title, item_title=item.item_title,
                         rating_key=item.rating_key),
            title=u"%s (%s)" % (item.item_title, _(item.mode_verbose)),
            summary=_(u"%s in %s (%s, score: %s), %s", language_display, item.section_title,
                                                       _(item.provider_name), item.score, df(item.time)),
            thumb=item.thumb or default_thumb
        ))

    history.destroy()

    return oc


@route(PREFIX + '/missing/refresh')
@debounce
def RefreshMissing(randomize=None):
    scheduler.dispatch_task("SearchAllRecentlyAddedMissing")
    header = "Refresh of recently added items with missing subtitles triggered"
    return fatality(header=header, replace_parent=True)


def replace_item(obj, key, replace_value):
    for k, v in obj.items():
        if isinstance(v, dict):
            obj[k] = replace_item(v, key, replace_value)
    if key in obj:
        obj[key] = replace_value
    return obj


def check_connections():
    # debug drone
    Log.Debug("Checking connections ...")
    log_buffer = []
    try:
        from subliminal_patch.refiners.drone import SonarrClient, RadarrClient
        log_buffer.append(["----- Connections -----"])
        for key, cls in [("sonarr", SonarrClient), ("radarr", RadarrClient)]:
            if key in config.refiner_settings:
                cname = key.capitalize()
                try:
                    status = cls(**config.refiner_settings[key]).status(timeout=5)
                except HTTPError, e:
                    if e.response.status_code == 401:
                        log_buffer.append(("%s: NOT WORKING - BAD API KEY", cname))
                    else:
                        log_buffer.append(("%s: NOT WORKING - %s", cname, traceback.format_exc()))
                except:
                    log_buffer.append(("%s: NOT WORKING - %s", cname, traceback.format_exc()))
                else:
                    if status and status["version"]:
                        log_buffer.append(("%s: OK - %s", cname, status["version"]))
                    else:
                        log_buffer.append(("%s: NOT WORKING - %s", cname))
    except:
        log_buffer.append(("Something went really wrong when evaluating Sonarr/Radarr: %s", traceback.format_exc()))
    finally:
        Core.log.setLevel(logging.DEBUG)
        for entry in log_buffer:
            Log.Debug(*entry)

        Core.log.setLevel(logging.getLevelName(Prefs["log_level"]))


@route(PREFIX + '/ValidatePrefs', enforce_route=True)
def ValidatePrefs():
    Core.log.setLevel(logging.DEBUG)

    if Prefs["log_console"]:
        Core.log.addHandler(logger.console_handler)
        Log.Debug("Logging to console from now on")
    else:
        Core.log.removeHandler(logger.console_handler)
        Log.Debug("Stop logging to console")

    # cache the channel state
    update_dict = False
    restart = False

    # reset pin
    Dict["pin_correct_time"] = None

    config.initialize()
    if "channel_enabled" not in Dict:
        update_dict = True

    elif Dict["channel_enabled"] != config.enable_channel:
        Log.Debug("Interface features %s, restarting plugin", "enabled" if config.enable_channel else "disabled")
        update_dict = True
        restart = True

    if "plugin_pin_mode2" not in Dict:
        update_dict = True

    elif Dict["plugin_pin_mode2"] != Prefs["plugin_pin_mode2"]:
        update_dict = True
        restart = True

    if update_dict:
        Dict["channel_enabled"] = config.enable_channel
        Dict["plugin_pin_mode2"] = Prefs["plugin_pin_mode2"]
        Dict.Save()

    if restart:
        scheduler.stop()
        DispatchRestart()
        return

    scheduler.setup_tasks()
    scheduler.clear_task_data("MissingSubtitles")
    set_refresh_menu_state(None)

    Log.Debug("Validate Prefs called.")

    # SZ config debug
    Log.Debug("--- SZ Config-Debug ---")
    for attr in [
            "version", "app_support_path", "data_path", "data_items_path", "enable_agent",
            "enable_channel", "permissions_ok", "missing_permissions", "fs_encoding",
            "subtitle_destination_folder", "include", "include_exclude_paths", "include_exclude_sz_files",
            "new_style_cache", "dbm_supported", "lang_list", "providers", "normal_subs", "forced_only", "forced_also",
            "plex_transcoder", "refiner_settings", "unrar", "adv_cfg_path", "use_custom_dns",
            "has_anticaptcha", "anticaptcha_cls", "mediainfo_bin"]:

        value = getattr(config, attr)
        if isinstance(value, dict):
            d = replace_item(copy.deepcopy(value), "api_key", "<KEY>")
            Log.Debug("config.%s: %s", attr, d)
            continue

        if attr in ("api_key",):
            value = "<KEY>"

        Log.Debug("config.%s: %s", attr, value)

    for attr in ["plugin_log_path", "server_log_path"]:
        value = getattr(config, attr)

        if value:
            access = os.access(value, os.R_OK)
            if Core.runtime.os == "Windows":
                try:
                    f = open(value, "r")
                    f.read(1)
                    f.close()
                except:
                    access = False

        Log.Debug("config.%s: %s (accessible: %s)", attr, value, access)

    for attr in [
            "subtitles.save.filesystem", ]:
        Log.Debug("Pref.%s: %s", attr, Prefs[attr])

    if "sonarr" in config.refiner_settings or "radarr" in config.refiner_settings:
        Thread.Create(check_connections)

    # fixme: check existance of and os access of logs
    Log.Debug("----- Environment -----")
    Log.Debug("Platform: %s", Core.runtime.platform)
    Log.Debug("OS: %s", Core.runtime.os)
    Log.Debug("Python: %s", platform.python_version())
    for key, value in os.environ.iteritems():
        if key.startswith("PLEX") or key.startswith("SZ_"):
            if "TOKEN" in key:
                outval = "xxxxxxxxxxxxxxxxxxx"

            else:
                outval = value
            Log.Debug("%s: %s", key, outval)
    Log.Debug("Locale: %s", locale.getdefaultlocale())
    Log.Debug("-----------------------")

    Log.Debug("Setting log-level to %s", Prefs["log_level"])
    logger.register_logging_handler(DEPENDENCY_MODULE_NAMES, level=Prefs["log_level"])
    Core.log.setLevel(logging.getLevelName(Prefs["log_level"]))
    os.environ['U1pfT01EQl9LRVk'] = '789CF30DAC2C8B0AF433F5C9AD34290A712DF30D7135F12D0FB3E502006FDE081E'

    return

# coding=utf-8 # init GUI # default thumb for DirectoryObjects displays the contents of a section filtered by the first letter     :param rating_key: actually is the section's key     :param key: the firstLetter wanted     :param title: the first letter, or #     :param deeper:     :return: displays the contents of a section based on whether it has a deeper tree or not (movies->movie (item) list; series->series list)     :param rating_key:     :param title:     :param base_title:     :param display_items:     :param previous_item_type:     :param previous_rating_key:     :return: # add back to series for season # it shouldn't take more than 6 minutes to scan all of a series' files and determine the force refresh # we don't know exactly where we are here, only add ignore option to series # mass-extract embedded # add refresh # debug drone # cache the channel state # reset pin # SZ config debug # fixme: check existance of and os access of logs