from django import forms
from django.conf import settings
from django.core.validators import RegexValidator
from django.db import models
from django.shortcuts import redirect
from django.utils.decorators import method_decorator
from django.views.generic import FormView, ListView

from activities.models import Emoji
from users.decorators import moderator_required
from users.views.admin.generic import HTMXActionView


@method_decorator(moderator_required, name="dispatch")
class EmojiRoot(ListView):

    template_name = "admin/emoji.html"
    paginate_by = 50

    def get(self, request, *args, **kwargs):
        self.query = request.GET.get("query")
        self.local_only = request.GET.get("local_only")
        self.extra_context = {
            "section": "emoji",
            "query": self.query or "",
            "local_only": self.local_only,
        }
        return super().get(request, *args, **kwargs)

    def get_queryset(self):
        queryset = Emoji.objects.filter().order_by("shortcode", "domain_id")
        if self.local_only:
            queryset = queryset.filter(local=True)
        if self.query:
            query = self.query.lower().strip().lstrip("@")
            queryset = queryset.filter(
                models.Q(shortcode__icontains=query) | models.Q(domain_id=query)
            )
        return queryset


@method_decorator(moderator_required, name="dispatch")
class EmojiCreate(FormView):

    template_name = "admin/emoji_create.html"
    extra_context = {"section": "emoji"}

    class form_class(forms.Form):
        shortcode = forms.SlugField(
            help_text="What users type to use the emoji :likethis:\nShould only contain 0-9, a-z and underscores",
            validators=[
                RegexValidator(r"^[a-z0-9_]+$", message="Invalid emoji shortcode")
            ],
        )
        image = forms.ImageField(
            help_text=f"The emoji image\nShould be at least 40 x 40 pixels, and under {settings.SETUP.EMOJI_MAX_IMAGE_FILESIZE_KB}KB",
        )

        def clean_image(self):
            data = self.cleaned_data["image"]
            if data.size > settings.SETUP.EMOJI_MAX_IMAGE_FILESIZE_KB * 1024:
                raise forms.ValidationError(
                    f"Image filesize is too large (actual: {data.size // 1024}KB)"
                )
            if data.image.width < 40 or data.image.height < 40:
                raise forms.ValidationError(
                    f"Image should at least 40 x 40 pixels (actual: {data.image.width} x {data.image.height} pixels)"
                )
            return data

    def form_valid(self, form):
        Emoji.objects.create(
            shortcode=form.cleaned_data["shortcode"],
            file=form.cleaned_data["image"],
            mimetype=form.cleaned_data["image"].image.get_format_mimetype(),
            local=True,
            public=True,
        )
        return redirect(Emoji.urls.admin)


@method_decorator(moderator_required, name="dispatch")
class EmojiDelete(HTMXActionView):
    """
    Deletes an emoji
    """

    model = Emoji

    def action(self, emoji: Emoji):
        emoji.delete()


@method_decorator(moderator_required, name="dispatch")
class EmojiEnable(HTMXActionView):
    """
    Sets an emoji to be enabled (or not!)
    """

    model = Emoji
    enable = True

    def action(self, emoji: Emoji):
        emoji.public = self.enable
        emoji.save()


@method_decorator(moderator_required, name="dispatch")
class EmojiCopyLocal(HTMXActionView):
    """
    Duplicates a domain emoji to be local, as long as it is usable and the
    shortcode is available.
    """

    model = Emoji

    def action(self, emoji: Emoji):
        # Force reload locals cache to avoid potential for shortcode dupes
        Emoji.locals = Emoji.load_locals()
        emoji.copy_to_local()
