from plone import api
from plone.app.dexterity.textindexer.directives import searchable
from plone.autoform import directives
from plone.dexterity.content import Container
from plone.namedfile.field import NamedBlobImage
from plone.supermodel import model
from ploneintranet.core import _
from Products.membrane.interfaces import IGroup
from Products.membrane.interfaces import IMembraneGroupProperties
from Products.PlonePAS.sheet import MutablePropertySheet
from z3c.form import validator
from zope import schema
from zope.interface import implementer
from zope.interface import Invalid


class IWorkGroup(model.Schema, IGroup, IMembraneGroupProperties):
    """The core group schema.

    Most of the plone intranet UI relies on these fields.
    """

    searchable("id")
    id = schema.TextLine(title=_("ID"), required=True, missing_value="")
    canonical = schema.TextLine(
        title=_("Canonical Group ID (may contain spaces)"),
        required=False,
        default="",
        missing_value="",
    )
    searchable("title")
    title = schema.TextLine(
        title=_("Title"), required=False, default="", missing_value=""
    )
    searchable("description")
    description = schema.TextLine(
        title=_("Description"), required=False, default="", missing_value=""
    )
    searchable("email")
    email = schema.TextLine(
        title=_("Email"), required=False, default="", missing_value=""
    )
    members = schema.Set(
        value_type=schema.TextLine(
            title=_("label_member_id", "ID of a member"), required=True, default=""
        ),
        title=_("Members"),
        required=False,
        defaultFactory=set,
        missing_value=set(),
    )
    image = NamedBlobImage(
        title=_("Logo"),
        description=_("Group logo. A square image will work best."),
        required=False,
    )
    directives.write_permission(source="cmf.ManagePortal")
    directives.read_permission(source="cmf.ManagePortal")
    source = schema.TextLine(
        title=_("Source (plone, LDAP, XLS, ...)"),
        required=False,
        default="plone",
    )


@implementer(IWorkGroup)
class WorkGroup(Container):
    """Work Group content type."""

    def Title(self):
        """
        return the title
        """
        return self.title

    def Description(self):
        """
        return the description
        """
        return self.description

    def Email(self):
        """
        return the email
        """
        return self.email

    def getGroupId(self):
        """
        return the group id
        """
        return self.canonical or self.id

    def getGroupName(self):
        return self.title

    def getGroupMembers(self):
        """
        return the members of the given group
        """
        # XXX filter for really existing members
        return self.members

    workspace_members = getGroupMembers

    def getRoles(self):
        """
        return the roles that group members should gain
        """
        return []

    def getPropertiesForUser(self, user, request=None):
        """Get properties for this group."""
        properties = {
            "id": self.canonical,
            "title": self.title,
            "description": self.description or "",
            "email": self.email or "",
            "canonical": self.canonical,
            "object_id": self.id,
        }
        return MutablePropertySheet(**properties)


class WorkGroupIdValidator(validator.SimpleFieldValidator):
    """Two users can't have the same username."""

    def validate(self, value, force=False):
        membrane_tool = api.portal.get_tool("membrane_tool")
        groupids = membrane_tool._catalog.uniqueValuesFor("exact_getGroupId")
        if value in groupids:
            brains = membrane_tool.searchResults(exact_getGroupId=value)
            if brains and self.context != brains[0].getObject():
                raise Invalid(_("A group with this id already exists"))

        return super().validate(value)


validator.WidgetValidatorDiscriminators(WorkGroupIdValidator, field=IWorkGroup["id"])
