"""
Views file for theming administration.
"""

from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.shortcuts import redirect
from django.template.loader import render_to_string
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
from openedx.core.djangoapps.user_api.preferences.api import (
    delete_user_preference,
    get_user_preference,
    set_user_preference,
)
from openedx.core.djangoapps.util.user_messages import PageLevelMessages
from student.roles import GlobalStaff
from web_fragments.fragment import Fragment

from .helpers import theme_exists
from .models import SiteTheme

PREVIEW_SITE_THEME_PREFERENCE_KEY = 'preview-site-theme'
PREVIEW_THEME_FIELD = 'preview_theme'


def user_can_preview_themes(user):
    """
    Returns true if the specified user is allowed to preview themes.
    """
    if not user or user.is_anonymous():
        return False

    # In development mode, all users can preview themes
    if settings.DEBUG:
        return True

    # Otherwise, only global staff can preview themes
    return GlobalStaff().has_user(user)


def get_user_preview_site_theme(request):
    """
    Returns the preview site for the current user, or None if not set.
    """
    user = request.user
    if not user or user.is_anonymous():
        return None
    preview_site_name = get_user_preference(user, PREVIEW_SITE_THEME_PREFERENCE_KEY)
    if not preview_site_name:
        return None
    return SiteTheme(site=request.site, theme_dir_name=preview_site_name)


def set_user_preview_site_theme(request, preview_site_theme):
    """
    Sets the current user's preferred preview site theme.

    Args:
        request: the current request
        preview_site_theme (str or SiteTheme): the preview site theme or theme name.
          None can be specified to remove the preview site theme.
    """
    if preview_site_theme:
        if isinstance(preview_site_theme, SiteTheme):
            preview_site_theme_name = preview_site_theme.theme_dir_name
        else:
            preview_site_theme_name = preview_site_theme
        if theme_exists(preview_site_theme_name):
            set_user_preference(request.user, PREVIEW_SITE_THEME_PREFERENCE_KEY, preview_site_theme_name)
            PageLevelMessages.register_success_message(
                request,
                _('Site theme changed to {site_theme}'.format(site_theme=preview_site_theme_name))
            )
        else:
            PageLevelMessages.register_error_message(
                request,
                _('Theme {site_theme} does not exist'.format(site_theme=preview_site_theme_name))
            )
    else:
        delete_user_preference(request.user, PREVIEW_SITE_THEME_PREFERENCE_KEY)
        PageLevelMessages.register_success_message(request, _('Site theme reverted to the default'))


class ThemingAdministrationFragmentView(EdxFragmentView):
    """
    Fragment view to allow a user to administer theming.
    """

    def render_to_fragment(self, request, course_id=None, **kwargs):
        """
        Renders the theming administration view as a fragment.
        """
        html = render_to_string('theming/theming-admin-fragment.html', {})
        return Fragment(html)

    @method_decorator(login_required)
    def get(self, request, *args, **kwargs):
        """
        Renders the theming admin fragment to authorized users.
        """
        if not user_can_preview_themes(request.user):
            raise Http404
        return super(ThemingAdministrationFragmentView, self).get(request, *args, **kwargs)

    @method_decorator(login_required)
    def post(self, request, **kwargs):
        """
        Accept requests to update the theme preview.
        """
        if not user_can_preview_themes(request.user):
            raise Http404
        action = request.POST.get('action', None)
        if action == 'set_preview_theme':
            preview_theme_name = request.POST.get(PREVIEW_THEME_FIELD, '')
            set_user_preview_site_theme(request, preview_theme_name)
        elif action == 'reset_preview_theme':
            set_user_preview_site_theme(request, None)
        return redirect(request.path)

    def create_base_standalone_context(self, request, fragment, **kwargs):
        """
        Creates the context to use when rendering a standalone page.
        """
        return {
            'uses_bootstrap': True,
        }

    def standalone_page_title(self, request, fragment, **kwargs):
        """
        Returns the page title for the standalone update page.
        """
        return _('Theming Administration')
