"""Users (principals) for the WAeUP portal.
"""
import grok
from zope.event import notify
from zope.interface import Interface
from zope.securitypolicy.interfaces import IPrincipalRoleMap
from waeup.sirp.authentication import Account
from waeup.sirp.interfaces import IUserContainer, ILocalRoleSetEvent

class UserContainer(grok.Container):
    """A container for principals.

    See interfaces.py and users.txt for extensive description.
    """
    grok.implements(IUserContainer)
    grok.require('waeup.manageUsers')

    def addUser(self, name, password, title=None, description=None, roles=[]):
        """Add a new Account instance, created from parameters.
        """
        if title is None:
            title = name
        if description is None:
            description = title
        self[name] = Account(name, password, title, description, roles)

    def addAccount(self, account):
        """Add the account passed.
        """
        self[account.name] = account

    def delUser(self, name):
        """Delete user, if an account with the given name exists.

        Do not complain, if the name does not exist.
        """
        if name in self.keys():
            del self[name]

class LocalRoleSetEvent(object):

    grok.implements(ILocalRoleSetEvent)

    def __init__(self, object, role_id, principal_id, granted=True):
        self.object = object
        self.role_id = role_id
        self.principal_id = principal_id
        self.granted = granted

@grok.subscribe(Interface, ILocalRoleSetEvent)
def handle_local_role_changed(obj, event):
    site = grok.getSite()
    if site is None:
        return
    users = site.get('users', None)
    if users is None:
        return
    role_id = event.role_id
    if event.principal_id not in users.keys():
        return
    user = users[event.principal_id]
    user.notifyLocalRoleChanged(event.object, event.role_id, event.granted)
    return

@grok.subscribe(Interface, grok.IObjectRemovedEvent)
def handle_local_roles_on_obj_removed(obj, event):
    try:
        role_map = IPrincipalRoleMap(obj)
    except TypeError:
        # no map, no roles to remove
        return
    for local_role, user_name, setting in role_map.getPrincipalsAndRoles():
        notify(LocalRoleSetEvent(
                obj, local_role, user_name, granted=False))
    return
