from AccessControl import ClassSecurityInfo
from ExtensionClass import Base
from Acquisition import Implicit
from Acquisition import aq_base, aq_parent, aq_inner
import re
security = ClassSecurityInfo()

def getCertificateObject(self,st_entry):
    try:
        return getattr(getattr(getattr(self.portal_url.getPortalObject().campus.academics,st_entry.faculty),
                               st_entry.department).certificates,st_entry.course)
    except:
        return None

security.declarePublic('getRolesInContext')
def getRolesInContext(self, object):
    """Get the list of roles assigned to the user.
    This includes local roles assigned in the context of
    the passed in object.
    Knows about local roles blocking (roles starting with '-').
    """
    name = self.getUserName()
    roles = self.getRoles()
    # deal with groups
    groups = self.getComputedGroups()
    # end groups
    local = {}
    stop_loop = 0
    real_object = object
    object = aq_inner(object)
    while 1:
        # Collect all roles info
        lrd = {}
        local_roles = getattr(object, '__ac_local_roles__', None)
        if local_roles:
            if callable(local_roles):
                local_roles = local_roles() or {}
            for r in local_roles.get(name, ()):
                if r:
                    lrd[r] = None
        local_group_roles = getattr(object, '__ac_local_group_roles__', None)
        if local_group_roles:
            if callable(local_group_roles):
                local_group_roles = local_group_roles() or {}
            for g in groups:
                for r in local_group_roles.get(g, ()):
                    if r:
                        lrd[r] = None
        lr = lrd.keys()
        # Positive role assertions
        for r in lr:
            if r[0] != '-':
                if not local.has_key(r):
                    local[r] = 1 # acquired role
        # Negative (blocking) role assertions
        for r in lr:
            if r[0] == '-':
                r = r[1:]
                if not r:
                    # role '-' blocks all acquisition
                    stop_loop = 1
                    break
                if not local.has_key(r):
                    local[r] = 0 # blocked role
        if stop_loop:
            break
        if hasattr(object, 'aq_parent'):
            object = aq_inner(object.aq_parent)
            continue
        if hasattr(object, 'im_self'):
            object = aq_inner(object.im_self)
            continue
        break
    roles = list(roles)
    for r, v in local.items():
        if v: # only if not blocked
            roles.append(r)
    ## patch to assign dynamic roles for WAeUP
    while 1:
        #if self.isStudent():
        #    break
        # if re.match(r'\D\d\d\d\d\d\d',name):
        #    break
        #if len(name) != 7:
        #    break
        #try:
        #    int(name[1:])
        #except:
        #    break
        o = ord(name[1])
        if o >= 48 and o <= 57:
            break
        groups = self.portal_membership.getAuthenticatedMember().getGroups()
        if not ("ClearanceOfficers" in groups or "CourseAdvisers" in groups):
            break
        if callable(real_object) and hasattr(real_object,'im_self'):
            real_object = real_object.im_self

        if real_object is None:
            break
        if hasattr(real_object,'portal_type') and\
                   real_object.portal_type not in ("Student",
                                                   "StudentClearance",
                                                   "StudentStudyLevel",
                                                   "StudentCourseResult",
                                                  ):
            break

        # don't test if it is not a proxy
        #if real_object.portal_type == real_object.meta_type:
        #    break

        # can be later simplified by replacing by students_catalog values - Henrik
        # getattr works always because of acquisition ?! Henrik
        # sc = getattr(real_object,'study_course',None)
        # if sc is None:
        #     break
        # sc_obj = sc.getContent()
        # cert_id = sc_obj.study_course
        # res_cert = self.portal_catalog(id = cert_id)
        # if len(res_cert) != 1:
        #     break
        # certificate_brain = res_cert[0]
        # certificate_obj = certificate_brain.getObject()
        # cert_path = certificate_brain.getPath().split('/')
        # fac_id = cert_path[-4]
        # dep_id = cert_path[-3]
        # temporary self-healing function
        # deprecated after reindexing the students_catalog
        student_id = self.getStudentId()
        res = self.students_catalog(id=student_id)
        if len(res) != 1:
            break
        st_entry = res[0]
        # if st_entry.faculty != fac_id or\
        #    st_entry.department != dep_id or\
        #    st_entry.course != cert_id:
        #        self.students_catalog.modifyRecord(id = student_id,
        #                                         faculty = fac_id,
        #                                         department = dep_id,
        #                                         course = cert_id
        #                                         )
        if real_object.portal_type in ("StudentStudyLevel","StudentCourseResult"):
            # res_cert = self.portal_catalog(id = st_entry.course)
            # if len(res_cert) != 1:
            #     break
            # certificate_brain = res_cert[0]
            # certificate_obj = certificate_brain.getObject()
            certificate_obj = getCertificateObject(self,st_entry)
            if certificate_obj is None:
                #from pdb import set_trace;set_trace()
                break
            if real_object.meta_type.endswith('Folder'): # it is a proxy
                object = real_object
            else:
                object = real_object.aq_parent
            if real_object.portal_type == "StudentStudyLevel":
                level = object.getId()
            elif real_object.portal_type == "StudentCourseResult":
                level = object.aq_parent.getId()
            context_obj = getattr(certificate_obj,level,None)
            if context_obj is None:
                #from pdb import set_trace;set_trace()
                break
            allowed = set(('CourseAdviser', 'SectionManager'))
        elif real_object.portal_type == "Student" and "CourseAdvisers" in groups:
            #we need some special processing since CourseAdvisers are only
            #specified per StudyLevel
            certificate_obj = getCertificateObject(self,st_entry)
            if certificate_obj is None:
                #from pdb import set_trace;set_trace()
                break
            allowed = set(('CourseAdviser', 'SectionManager'))
            for context_obj in certificate_obj.objectValues():
                dynamic_roles = set(self.getRolesInContext(context_obj))
                intersect = dynamic_roles & allowed
                if intersect:
                    roles.extend(list(intersect))
            break
        else:
            res = self.portal_catalog(portal_type="Department",id=st_entry.department)
            allowed = set(('ClearanceOfficer', 'SectionManager'))
            if len(res) != 1:
                break
            context_obj = res[0].getObject()
        dynamic_roles = set(self.getRolesInContext(context_obj))
        intersect = dynamic_roles & allowed
        if intersect:
            roles.extend(list(intersect))
        break
    return roles

from Products.CPSUserFolder.CPSUserFolder import CPSUser
CPSUser.getRolesInContext = getRolesInContext
