# -*- coding: utf-8 -*-
from functools import update_wrapper
import os

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext_lazy as _
from django.utils.six.moves.urllib.parse import urljoin

from cms import constants


__all__ = ['get_cms_setting']


class VERIFIED: pass  # need a unique identifier for CMS_LANGUAGES


def default(name):
    def decorator(wrapped):
        def wrapper():
            if hasattr(settings, name):
                return getattr(settings, name)
            return wrapped()

        update_wrapper(wrapper, wrapped)
        return wrapped

    return decorator


DEFAULTS = {
    'TEMPLATE_INHERITANCE': True,
    'TOOLBAR_SIMPLE_STRUCTURE_MODE': True,
    'PLACEHOLDER_CONF': {},
    'PERMISSION': False,
    # Whether to use raw ID lookups for users when PERMISSION is True
    'RAW_ID_USERS': False,
    'PUBLIC_FOR': 'all',
    'CONTENT_CACHE_DURATION': 60,
    'APPHOOKS': [],
    'TOOLBARS': [],
    'SITE_CHOICES_CACHE_KEY': 'CMS:site_choices',
    'PAGE_CHOICES_CACHE_KEY': 'CMS:page_choices',
    'MEDIA_PATH': 'cms/',
    'PAGE_MEDIA_PATH': 'cms_page_media/',
    'TITLE_CHARACTER': '+',
    'PAGE_CACHE': True,
    'PLACEHOLDER_CACHE': True,
    'PLUGIN_CACHE': True,
    'CACHE_PREFIX': 'cms-',
    'PLUGIN_PROCESSORS': [],
    'PLUGIN_CONTEXT_PROCESSORS': [],
    'UNIHANDECODE_VERSION': None,
    'UNIHANDECODE_DECODERS': ['ja', 'zh', 'kr', 'vn', 'diacritic'],
    'UNIHANDECODE_DEFAULT_DECODER': 'diacritic',
    'MAX_PAGE_PUBLISH_REVERSIONS': 10,
    'MAX_PAGE_HISTORY_REVERSIONS': 15,
    'TOOLBAR_ANONYMOUS_ON': True,
    'TOOLBAR_URL__EDIT_ON': 'edit',
    'TOOLBAR_URL__EDIT_OFF': 'edit_off',
    'TOOLBAR_URL__BUILD': 'build',
    'TOOLBAR_URL__DISABLE': 'toolbar_off',
    'ADMIN_NAMESPACE': 'admin',
    'APP_NAME': None,
    'TOOLBAR_HIDE': False
}


def get_cache_durations():
    return {
        'menus': getattr(settings, 'MENU_CACHE_DURATION', 60 * 60),
        'content': get_cms_setting('CONTENT_CACHE_DURATION'),
        'permissions': 60 * 60,
    }


@default('CMS_MEDIA_ROOT')
def get_media_root():
    return os.path.join(settings.MEDIA_ROOT, get_cms_setting('MEDIA_PATH'))


@default('CMS_MEDIA_URL')
def get_media_url():
    return urljoin(settings.MEDIA_URL, get_cms_setting('MEDIA_PATH'))


@default('CMS_TOOLBAR_URL__EDIT_ON')
def get_toolbar_url__edit_on():
    return get_cms_setting('TOOLBAR_URL__EDIT_ON')


@default('CMS_TOOLBAR_URL__EDIT_OFF')
def get_toolbar_url__edit_off():
    return get_cms_setting('TOOLBAR_URL__EDIT_OFF')


@default('CMS_TOOLBAR_URL__BUILD')
def get_toolbar_url__build():
    return get_cms_setting('TOOLBAR_URL__BUILD')


@default('CMS_TOOLBAR_URL__DISABLE')
def get_toolbar_url__disable():
    return get_cms_setting('TOOLBAR_URL__DISABLE')


def get_templates():
    from cms.utils.django_load import load_from_file
    if getattr(settings, 'CMS_TEMPLATES_DIR', False):
        tpldir = getattr(settings, 'CMS_TEMPLATES_DIR', False)
        # CMS_TEMPLATES_DIR can either be a string poiting to the templates directory
        # or a dictionary holding 'site: template dir' entries
        if isinstance(tpldir, dict):
            tpldir = tpldir[settings.SITE_ID]
        # We must extract the relative path of CMS_TEMPLATES_DIR to the neares
        # valid templates directory. Here we mimick what the filesystem and
        # app_directories template loaders do
        prefix = ''
        # Relative to TEMPLATE_DIRS for filesystem loader

        try:
            path = settings.TEMPLATE_DIRS
        except IndexError:
            path = [template['DIRS'][0] for template in settings.TEMPLATES]

        for basedir in path:
            if tpldir.find(basedir) == 0:
                prefix = tpldir.replace(basedir + os.sep, '')
                break
        # Relative to 'templates' directory that app_directory scans
        if not prefix:
            components = tpldir.split(os.sep)
            try:
                prefix = os.path.join(*components[components.index('templates') + 1:])
            except ValueError:
                # If templates is not found we use the directory name as prefix
                # and hope for the best
                prefix = os.path.basename(tpldir)
        config_path = os.path.join(tpldir, '__init__.py')
        # Try to load templates list and names from the template module
        # If module file is not present skip configuration and just dump the filenames as templates
        if config_path:
            template_module = load_from_file(config_path)
            templates = [(os.path.join(prefix, data[0].strip()), data[1]) for data in template_module.TEMPLATES.items()]
        else:
            templates = list((os.path.join(prefix, tpl), tpl) for tpl in os.listdir(tpldir))
    else:
        templates = list(getattr(settings, 'CMS_TEMPLATES', []))
    if get_cms_setting('TEMPLATE_INHERITANCE'):
        templates.append((constants.TEMPLATE_INHERITANCE_MAGIC, _(constants.TEMPLATE_INHERITANCE_LABEL)))
    return templates


def _ensure_languages_settings(languages):
    valid_language_keys = ['code', 'name', 'fallbacks', 'hide_untranslated', 'redirect_on_fallback', 'public']
    required_language_keys = ['code', 'name']
    simple_defaults = ['public', 'redirect_on_fallback', 'hide_untranslated']

    if not isinstance(languages, dict):
        raise ImproperlyConfigured(
            "CMS_LANGUAGES must be a dictionary with site IDs and 'default'"
            " as keys. Please check the format.")

    defaults = languages.pop('default', {})
    default_fallbacks = defaults.get('fallbacks')
    needs_fallbacks = []

    for key in defaults:
        if key not in valid_language_keys:
            raise ImproperlyConfigured("CMS_LANGUAGES has an invalid property in the default properties: %s" % key)

    for key in simple_defaults:
        if key not in defaults:
            defaults[key] = True

    for site, language_list in languages.items():
        if site != hash(site):
            raise ImproperlyConfigured(
                "CMS_LANGUAGES can only be filled with integers (site IDs) and 'default'"
                " for default values. %s is not a valid key." % site)

        for language_object in language_list: