from DateTime import DateTime
from plone import api
from plone.memoize.view import memoize
from plone.memoize.view import memoize_contextless
from plone.protect.interfaces import IDisableCSRFProtection
from ploneintranet import api as pi_api
from ploneintranet.layout.interfaces import IModalPanel
from Products.Five import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.annotation import IAnnotations
from zope.interface import alsoProvides
from zope.interface import implementer

import datetime


class BaseView(BrowserView):
    """Base view that knows when it is called through ajax
    and if diazo should be disabled
    """

    @memoize
    def form_timestamp(self):
        """Return a timestamp, used in the form to create unique selectors"""
        return DateTime().strftime("%s")

    @memoize_contextless
    def is_posting(self):
        """Check if the user is posting"""
        return self.request.method == "POST"

    @memoize_contextless
    def is_ajax(self):
        """Check if we have an ajax call"""
        requested_with = self.request.environ.get("HTTP_X_REQUESTED_WITH")
        return requested_with == "XMLHttpRequest"

    def disable_csrf_protection(self):
        """Helper method to easily disable the CSRF protection."""
        alsoProvides(self.request, IDisableCSRFProtection)

    def maybe_disable_diazo(self):
        """Disable diazo if needed"""
        if self.is_ajax():
            self.request.response.setHeader("X-Theme-Disabled", "1")

    def redirect(self, target=None, msg="", msg_type="warning"):
        """"""
        if msg:
            api.portal.show_message(msg, self.request, msg_type)
        if not target:
            target = self.context
        if not isinstance(target, str):
            context_state = api.content.get_view(
                "plone_context_state", target, self.request
            )
            target = context_state.view_url()
        return self.request.response.redirect(target)

    def purge_memoize(self):
        """Purge the memoize cache, stored in the annotations.
        This is useful, e.g., after workflow state changes
        """
        IAnnotations(self.request).pop("plone.memoize", None)

    @property
    @memoize_contextless
    def user(self):
        """The currently authenticated ploneintranet user profile (if any)"""
        return pi_api.userprofile.get_current()

    def __call__(self):
        """Check if we can bookmark and render the template"""
        self.maybe_disable_diazo()
        return super().__call__()


@implementer(IModalPanel)
class BasePanel(BaseView):
    """Inherit from this if you want to create a modal panel"""

    body_child_class = "container"
    is_modal_panel = True
    panel_size = "medium"
    panel_style = "panel"
    show_button_bar = True
    show_default_cancel_button = True
    form_method = "post"
    _form_data_pat_inject_parts = (
        "#global-statusmessage; loading-class: ''",
        "#document-content",
    )

    @property
    @memoize
    def form_action(self):
        """The handler for this form"""
        return "{url}/@@{action}".format(
            url=self.context.absolute_url(), action=self.__name__
        )

    @property
    @memoize
    def form_data_pat_inject(self):
        """Merge the data inject parts to populate
        the form data-pat-inject attribute
        """
        return " && ".join(self._form_data_pat_inject_parts)

    def execute_on_post(self):
        """Override this if you want to execute something meaningful
        when some data are posted to this panel
        """

    def __call__(self):
        """Check if somebody posted some data before rendering the template.
        If as a consequence of this we have a redirect, skip rendering the template
        """
        if self.is_posting():
            self.execute_on_post()
            if self.request.response.headers.get("location"):
                return
        return super().__call__()


class BaseStatusView(BrowserView):
    """
    Base for status page views. Provides some formatting methods.
    """

    index = ViewPageTemplateFile("templates/status.pt")
    title = "Status"

    def __call__(self):
        return self.index()

    def all_check_names(self):
        return [
            method_name for method_name in dir(self) if method_name.startswith("check_")
        ]

    def all_checks(self):
        checks = [getattr(self, check_name) for check_name in self.all_check_names()]
        return [check for check in checks if hasattr(check, "__call__")]

    def time(self):
        return datetime.datetime.now().strftime("%H:%M:%S")

    def ok(self, check, msg="..."):
        return f"[OK] {check}: {msg}"

    def fail(self, check, msg="..."):
        return f"FAIL {check}: {msg}!"

    def warn(self, check, msg="..."):
        return f"WARN {check}: {msg}!"
