from django.contrib.auth.mixins import UserPassesTestMixin
from django.forms import ModelForm, ImageField
from django.urls import reverse

from filer.models.imagemodels import Image

from ..models import Page, Program, StaticPage
from .mixins import ParentMixin
from .page import PageDetailView, PageListView, PageUpdateView

__all__ = ["ProgramPageDetailView", "ProgramDetailView", "ProgramPageListView"]


class BaseProgramMixin:
    def get_program(self):
        return self.object

    def get_sidebar_url(self):
        return reverse("program-page-list", kwargs={"parent_slug": self.program.slug})

    def get_context_data(self, **kwargs):
        self.program = self.get_program()
        kwargs["program"] = self.program
        return super().get_context_data(**kwargs)


class ProgramDetailView(BaseProgramMixin, PageDetailView):
    model = Program

    def get_template_names(self):
        return super().get_template_names() + ["aircox/program_detail.html"]

    def get_sidebar_queryset(self):
        return super().get_sidebar_queryset().filter(parent=self.program)


class ProgramForm(ModelForm):
    new_cover = ImageField(required=False)

    class Meta:
        model = Program
        fields = ["content"]

    def save(self, commit=True):
        file_obj = self.cleaned_data["new_cover"]
        if file_obj:
            obj, _ = Image.objects.get_or_create(original_filename=file_obj.name, file=file_obj)
            self.instance.cover = obj
        super().save(commit=commit)


class ProgramUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView):
    model = Program
    form_class = ProgramForm

    def get_sidebar_queryset(self):
        return super().get_sidebar_queryset().filter(parent=self.program)

    def test_func(self):
        program = self.get_object()
        return self.request.user.has_perm("aircox.%s" % program.change_permission_codename)

    def get_success_url(self):
        return reverse("program-detail", kwargs={"slug": self.get_object().slug})


class ProgramListView(PageListView):
    model = Program
    attach_to_value = StaticPage.ATTACH_TO_PROGRAMS


# FIXME: not used
class ProgramPageDetailView(BaseProgramMixin, ParentMixin, PageDetailView):
    """Base view class for a page that is displayed as a program's child
    page."""

    parent_model = Program

    def get_program(self):
        self.parent = self.object.program
        return self.object.program

    def get_sidebar_queryset(self):
        return super().get_sidebar_queryset().filter(parent=self.program)


class ProgramPageListView(BaseProgramMixin, PageListView):
    model = Page
    parent_model = Program
    queryset = Page.objects.select_subclasses()

    def get_program(self):
        return self.parent

    def get_context_data(self, **kwargs):
        kwargs.setdefault("sidebar_url_parent", None)
        return super().get_context_data(**kwargs)
