##############################################################################
# Copyright (c) 2004-2005 Black Rock City, LLC
# Copyright (c) 2004-2005 ObjectRealms, LLC
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
##############################################################################
"""
Description: A roster to display members of teams

Created: June 18, 2004
$Id: roster.py 46903 2007-08-09 05:57:19Z rafrombrc $
"""

from zimport import *

from zope.interface import implements

from Products.Archetypes.public import ReferenceField, DisplayList

from Products.TeamSpace.config import MEMBER_CATALOG, USER_ID_VARIABLE

from relations import TeamRosterTeamRelation
from interfaces.roster import IRoster
from permissions import *
from sets import Set

roster_type_information = {
  'title'          : 'TeamRoster',
  'id'             : 'TeamRoster',
  'portal_type'    : 'TeamRoster',
  'meta_type'      : 'TeamRoster',
  'description'    : 'A List of Team Members',
  'content_icon'   : 'roster_icon.png',
  'product'        : 'TeamSpace',
  'factory'        : 'addTeamRoster',
  'global_allow'   : 1,
  'immediate_view' : 'base_edit',
  'filter_content_types' : 1,
  'allowed_content_types': (),
  'actions': (
    {
    'name'         : 'Member List',
    'id'           : 'view',
    'action'       : 'ts_team_list_view',
    'permissions'  : (ViewTeam,),
    'category'     : 'object',
    },
    {
    'name'         : 'Edit',
    'id'           : 'edit',
    'action'       : 'base_edit',
    'permissions'  : (ManageTeam,),
    'category'     : 'object',
    },
    {
    'name'         : 'Properties',
    'id'           : 'metadata',
    'action'       : 'base_metadata',
    'permissions'  : (ManageTeam,),
    'category'     : 'object',
    },
  ),
  }

factory_type_information = (roster_type_information,)

schema=BaseSchema.copy() + Schema((
    ReferenceField( 'assoc_teams',
                    required=1,
                    relationship = TeamRosterTeamRelation.relationship,
                    referenceClass = TeamRosterTeamRelation,
                    allowed_types = ('Team',),
                    mutator    = 'setTeams',
                    accessor   = 'getTeams',
                    multiValued = 1,
                    vocabulary = 'getTeamsVocab',
                    widget = ReferenceWidget( label="Associated Teams",
                                             label_msgid="label_team_roster",
                                             description="The teams for which this roster will display members.",
                                             description_msgid = "description_team_roster",
                                             ),
                    ),
    ))

def addTeamRoster(self, id, **kwargs):
    o = TeamRoster(id)
    self._setObject(id, o)
    o = getattr(self, id)
    o.initializeArchetype(**kwargs)
    return id

class TeamRoster( BaseContent ):
    
    """
    A Team Roster acts as a decentralize conduit for the display
    and management of a teams members.
    """
    
    implements(IRoster)
    portal_type = meta_type = "TeamRoster"
    archetype_name = "Team Roster"
    schema = schema

    _at_rename_after_creation = True
    
    security = ClassSecurityInfo()

    def getActiveMemberIds(self):
        """
        Returns the active members from all associated teams
        """
        teams = self.getTeams()
        # generate a unique list of mem_ids
        mem_ids = {}
        for team in teams:
            mem_ids.update(dict.fromkeys(team.getActiveMemberIds()))
        return mem_ids.keys()
        
    def rosterSearchResults(self, REQUEST=None, **kw):
        """
        Catalog search restricted by team ids
        """
        kw = kw.copy()
        kw[USER_ID_VARIABLE] = self.getActiveMemberIds()
        mcat_tool = getToolByName(self, MEMBER_CATALOG)
        results = mcat_tool.searchResults( REQUEST=REQUEST,
                                           **kw )
        return results

    def memberDisplayFields(self, method=None, **kw):
        """
        grab member type schema and filter for metadata fieldnames.
        uses filter fields: either feed it keywords or a method
        """
        at_tool = getToolByName(self, 'archetype_tool')
        mdc = getToolByName(self, 'portal_memberdata')

        schemas = [ klass.schema for klass in at_tool.listTypes() if \
                    klass.portal_type in mdc.allowed_content_types ]

        ## Do best we can for multiple member types
        
        if method:
            fieldsets = [ schema.filterFields(*method) for schema in schemas ]
        else:
            fieldsets = [ schema.filterFields(**kw) for schema in schemas ]
        
        if not fieldsets:
            return
        
        if len(fieldsets) == 1:
            fields =  fieldsets[0]
        else:
            # this will return non duplicate named fields
            # fields are returned(so sort on that if you need more)
            
            f_dict = {}
            fields = []
            [ fields.extend(fset) for fset in fieldsets ]
            
            def notdupe(x):
                if f_dict.has_key(x):
                    notdupe=False
                else:
                    f_dict[x]
                    notdupe=True
                return notdupe
            
            notdupe = notdupe
            fields = [ field for field in fields if notdupe(field.getName())]
                
        return fields

    security.declarePrivate('getTeamsVocab')
    def getTeamsVocab(self):
        """
        returns the vocabulary for the assoc_teams schema field.
        only includes the results of parent's getTeams() method,
        if this exists
        """
        if hasattr(self.aq_parent, 'getTeams'):
            getTeams = self.aq_parent.getTeams
        else:
            getTeams = getToolByName(self, 'portal_teams').getTeams

        teams = getTeams()
        pairs = [(team.UID(), '%s: %s' % (team.id, team.Title()))
                  for team in teams]
        vocab = DisplayList(pairs)

        return vocab

registerType(TeamRoster)
