from plone import api
from plone.base import PloneMessageFactory as __
from plone.memoize.view import memoize
from ploneintranet.core import _
from ploneintranet.layout.browser.actions import PIDeleteConfirmationForm
from ploneintranet.workspace.events import ObjectTrashedEvent
from ploneintranet.workspace.interfaces import ITrashed
from Products.CMFCore.interfaces import IFolderish
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from urllib.parse import urlencode
from z3c.form import button
from zope.event import notify
from zope.interface import alsoProvides


class TrashConfirmationForm(PIDeleteConfirmationForm):
    """Override the Delete confirmation view to just mark the document
    as trashed.

    Note: we need to override both the actions
    """

    trash_enabled = True
    panel_size = "small"

    @property
    @memoize
    def form_data_pat_inject(self):
        """Inject the trashed context"""
        dpi = ["#selector", "#document-body"]
        if self.request.get("origin") in ("sidebar", "context-menu"):
            dpi.append("#workspace-documents")
        return " && ".join(dpi)

    def recursively_mark_trashed(self, obj=None):
        """Mark obj as trashed and apply the same operation to all
        the contained objects
        """
        obj = obj or self.context
        if not ITrashed.providedBy(obj):
            alsoProvides(obj, ITrashed)
            notify(ObjectTrashedEvent(obj))
        if not IFolderish.providedBy(obj):
            return
        list(map(self.recursively_mark_trashed, obj.listFolderContents()))

    @button.buttonAndHandler(_("I am sure, move to trash now"), name="Delete")
    def handle_delete(self, action):
        """Mark the trash and its contents as trashed and return to the parent"""
        self.recursively_mark_trashed()
        msg = __(
            "${title} has been deleted.",
            mapping={"title": self.context.Title()},
        )
        api.portal.show_message(msg, self.request, type="success")
        self.request.response.redirect(
            self.context.absolute_url() + "/view?show_sidebar=1"
        )

    @button.buttonAndHandler(_("label_cancel", default="Cancel"), name="Cancel")
    def handle_cancel(self, action):
        return self.request.response.redirect(self.view_url())


class SuperspaceDeleteConfirmationForm(PIDeleteConfirmationForm):
    """Override the delete confirmation behavior for superspaces"""

    template = ViewPageTemplateFile("templates/superspace_delete_confirmation.pt")
    panel_size = "small"

    @property
    @memoize
    def superspace_uid(self):
        superspace = self.context.superspace
        if not superspace:
            return ""
        return superspace.to_object.UID()

    @property
    @memoize
    def parent_tile_uid(self):
        return self.superspace_uid[:6]

    @property
    @memoize
    def form_data_pat_inject(self):
        """Inject the trashed context"""
        dpi = []
        if self.parent_tile_uid:
            dpi_template = "source: #workspaces > .tiles; target: #subspaces-tile-{}"
            dpi.append(dpi_template.format(self.parent_tile_uid))
        else:
            dpi.append("source: #workspaces; target: #workspaces")
        dpi.append(
            "source: #global-statusmessage; "
            "target: #global-statusmessage; "
            "loading-class: ''"
        )
        return " && ".join(dpi)

    @property
    @memoize
    def superspace_view(self):
        """Get the superspace view"""
        return api.content.get_view("view", self.context, self.request)

    def additional_hidden_inputs(self):
        """Additional hidden inputs that may be used to control the form
        behavior (e.g. injection)
        """
        inputs = []
        if self.parent_tile_uid:
            inputs.append({"name": "tile_uid", "value": self.parent_tile_uid})
        return inputs

    @property
    def post_delete_url(self):
        """Go here after an object has been deleted"""
        url = self.context.aq_parent.absolute_url()
        superspace = self.context.superspace
        if not superspace:
            return url
        params = {"in_superspace": self.superspace_uid}
        return f"{url}?{urlencode(params)}"

    def __call__(self):
        """Do not allow to cancel superspaces with subspaces,
        even invisible ones.
        """
        if self.superspace_view.has_subspaces():
            api.portal.show_message(
                _("You can only delete super spaces that are empty."),
                request=self.request,
                type="warning",
            )
            return self.request.response.redirect(self.context.aq_parent.absolute_url())
        return super().__call__()
