"""passbook Policy administration"""
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.http import Http404
from django.urls import reverse_lazy
from django.utils.translation import ugettext as _
from django.views.generic import (CreateView, DeleteView, FormView, ListView,
                                  UpdateView)
from django.views.generic.detail import DetailView

from passbook.admin.forms.policies import PolicyTestForm
from passbook.admin.mixins import AdminRequiredMixin
from passbook.core.models import Policy
from passbook.core.policies import PolicyEngine
from passbook.lib.utils.reflection import path_to_class


class PolicyListView(AdminRequiredMixin, ListView):
    """Show list of all policies"""

    model = Policy
    template_name = 'administration/policy/list.html'

    def get_context_data(self, **kwargs):
        kwargs['types'] = {
            x.__name__: x._meta.verbose_name for x in Policy.__subclasses__()}
        return super().get_context_data(**kwargs)

    def get_queryset(self):
        return super().get_queryset().order_by('order').select_subclasses()


class PolicyCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
    """Create new Policy"""

    template_name = 'generic/create.html'
    success_url = reverse_lazy('passbook_admin:policies')
    success_message = _('Successfully created Policy')

    def get_form_class(self):
        policy_type = self.request.GET.get('type')
        model = next(x for x in Policy.__subclasses__()
                     if x.__name__ == policy_type)
        if not model:
            raise Http404
        return path_to_class(model.form)


class PolicyUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView):
    """Update policy"""

    model = Policy
    template_name = 'generic/update.html'
    success_url = reverse_lazy('passbook_admin:policies')
    success_message = _('Successfully updated Policy')

    def get_form_class(self):
        form_class_path = self.get_object().form
        form_class = path_to_class(form_class_path)
        return form_class

    def get_object(self, queryset=None):
        return Policy.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()


class PolicyDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView):
    """Delete policy"""

    model = Policy
    template_name = 'generic/delete.html'
    success_url = reverse_lazy('passbook_admin:policies')
    success_message = _('Successfully deleted Policy')

    def get_object(self, queryset=None):
        return Policy.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()

    def delete(self, request, *args, **kwargs):
        messages.success(self.request, self.success_message)
        return super().delete(request, *args, **kwargs)


class PolicyTestView(AdminRequiredMixin, DetailView, FormView):
    """View to test policy(s)"""

    model = Policy
    form_class = PolicyTestForm
    template_name = 'administration/policy/test.html'
    object = None

    def get_object(self, queryset=None):
        return Policy.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()

    def get_context_data(self, **kwargs):
        kwargs['policy'] = self.get_object()
        return super().get_context_data(**kwargs)

    def post(self, *args, **kwargs):
        self.object = self.get_object()
        return super().post(*args, **kwargs)

    def form_valid(self, form):
        policy = self.get_object()
        user = form.cleaned_data.get('user')
        policy_engine = PolicyEngine([policy])
        policy_engine.for_user(user).with_request(self.request).build()
        result = policy_engine.passing
        if result:
            messages.success(self.request, _('User successfully passed policy.'))
        else:
            messages.error(self.request, _("User didn't pass policy."))
        return self.render_to_response(self.get_context_data(form=form, result=result))