from AccessControl import Unauthorized
from collections import OrderedDict
from plone import api
from ploneintranet.core import _
from ploneintranet.workspace.browser.tiles.sidebar import BaseTile
from ploneintranet.workspace.policies import JOIN_POLICY
from ploneintranet.workspace.policies import PARTICIPANT_POLICY

import logging

logger = logging.getLogger(__name__)


class SidebarSettingsSecurity(BaseTile):
    """A view to serve as the security settings in the sidebar"""

    # There might be settings in the participant policy that are
    # not meant to be be shown in the UI, such as "Guest". Exclude them.
    participant_policy = OrderedDict(
        [
            item
            for item in list(PARTICIPANT_POLICY.items())
            if not item[1].get("exclude_from_ui")
        ]
    )

    # Those are the fields managed by this sidebar
    security_fields = {
        "accessible_to_intranet_users",
        "visible_to_intranet_users",
        "join_policy",
        "participant_policy",
    }

    @property
    def join_policy_options(self):
        """Used to create the join policy selector in the page template"""
        selected_value = self.context.join_policy
        return [
            {
                "value": key,
                "label": value["help"],
                "checked": "checked" if selected_value == key else None,
            }
            for key, value in JOIN_POLICY.items()
        ]

    @property
    def participant_policy_options(self):
        """Used to create the participant policy selector in the page template"""
        selected_value = self.context.participant_policy
        return [
            {
                "value": key,
                "title": value["title"],
                "description": value["help"],
                "checked": "checked" if selected_value == key else None,
            }
            for key, value in self.participant_policy.items()
        ]

    @property
    def extranet_enabled(self):
        return api.portal.get_registry_record(
            "ploneintranet.userprofile.extranet_enabled", default=False
        )

    def accessible_to_intranet_users_checked(self):
        if self.context.accessible_to_intranet_users:
            return "checked"

    def visible_to_intranet_users_checked(self):
        """Also check for the object is accessible to intranet users,
        because that permission implies it is visible
        """
        if self.context.visible_to_intranet_users:
            return "checked"
        return self.accessible_to_intranet_users_checked()

    def update_security(self):
        """Update visibility and policies upon request"""
        form = self.request.form

        for field_name in ("accessible_to_intranet_users", "visible_to_intranet_users"):
            form[field_name] = bool(form.get(field_name))

        if not form.get("visible_to_intranet_users"):
            # We suppose that admins that do not want the workspace
            # visible to intranet users will also do not want it to be
            # accessible
            form["accessible_to_intranet_users"] = False

        ws = self.workspace()

        changed = False
        for field_name in self.security_fields:
            field = getattr(ws.__class__, field_name)
            value = form.get(field_name)

            if value != field.fget(ws):
                # update the field only if needed
                try:
                    field.fset(ws, value)
                    msg = _("Workspace security policy changes saved")
                    msg_type = "success"
                    changed = True
                except BaseException:
                    msg = _("Workspace security policy change failed")
                    logger.exception("Workspace security policy change failed")
                    msg_type = "error"
                api.portal.show_message(msg, self.request, msg_type)
        if changed:
            ws.reindexObject()

    @property
    def form_submitted(self):
        return bool(self.request.form)

    def __call__(self):
        """
        Write attributes, if any, set state, render
        """
        if self.request.method == "POST":
            if not self.workspace_view.can_manage_workspace():
                msg = _("You do not have permission to change the workspace " "policy")
                raise Unauthorized(msg)

            if self.form_submitted:
                self.update_security()

        return self.render()
