from collective.workspace.interfaces import IWorkspace
from plone import api
from plone.memoize.view import memoize
from ploneintranet.userprofile.browser.pas_graph import BaseGraphView
from ploneintranet.userprofile.browser.pas_graph import UserprofileGraphView
from ploneintranet.workspace.behaviors.group import IMembraneGroupMarker


class DynamicGroupsGraphView(BaseGraphView):

    pas_name = "dynamic_group"

    @property
    @memoize
    def uid(self):
        return self.join(self.context.getId())

    @memoize
    def get_edges(self):
        uid = self.uid
        pas_view = api.content.get_view("pas_view", api.portal.get(), self.request)
        return {
            (uid, memberuid)
            for memberuid in pas_view.uid2path
            if memberuid.startswith(UserprofileGraphView.pas_name)
        }


class WorkspaceGraphView(BaseGraphView):

    pas_name = "collective.workspace"

    @memoize
    def _is_quaive_group_active(self):
        """Check if the quaive.group behavior is active,
        this adds an additional membrane group that is basically a duplicate of the
        collective.workspace Members one
        TODO: remove support for this membrane group,
        we can use the collective.workspace Members instead
        """
        return IMembraneGroupMarker.providedBy(self.context)

    @memoize
    def get_node_info(self):
        if self._is_quaive_group_active():
            info = super().get_node_info()
        else:
            info = set()
        adapter = IWorkspace(self.context)
        for key in adapter.available_groups:
            uid = self.join(adapter.group_for_policy(key))
            name = uid
            path = self.join(key, self.context_path)
            info.add((uid, name, path))
        return info

    def get_edges(self):
        au = api.portal.get_tool("acl_users")
        mapping = au.workspace_groups._group_principal_map
        pas_view = api.content.get_view("pas_view", api.portal.get(), self.request)
        edges = set()

        members_groupuid = self.join("Members", self.context.UID())

        for node_info in self.get_node_info():
            groupuid = node_info[0]
            members = mapping.get(groupuid.partition(":")[-1], [])
            memberuids = map(pas_view.principalname2uid, members)
            for memberuid in memberuids:
                if memberuid:
                    edges.add((groupuid, memberuid))
                    if groupuid == members_groupuid and self._is_quaive_group_active():
                        edges.add((self.join(self.context.UID()), memberuid))
        return edges
