#-*- mode: python; mode: fold -*-
# $Id: install.py 195 2005-11-22 18:23:15Z joachim $
from Products.ExternalMethod.ExternalMethod import ExternalMethod
from Products.CPSInstaller.CPSInstaller import CPSInstaller
from Products.CMFCore.CMFCorePermissions import View, ModifyPortalContent,AccessContentsInformation
from Products.WAeUP.WAeUPPermissions import UniversityManage, StudentManage,FacultyManage,\
                                            DepartmentManage,CourseManage
try:
  from Products.CPSSubscriptions.permissions import CanNotifyContent
  CPSSubscriptions = True
except ImportError:
  CPSSubscriptions = False
try:
  from Products.CPSForum.CPSForumPermissions import ForumManageComments
  CPSForum = True
except ImportError:
  CPSForum = False

from Products.WAeUP.Students import addStudentsFolder

SRPP_ID = "demouni"
SRPP_TITLE = "Demo University"

class WAeUPInstaller(CPSInstaller):
    """
    WAeUP Installer
    """
    product_name = "WAeUP"

    def install(self,portal):
        "install"
        log = []
        prlog = log.append

        def pr(msg, prlog=prlog):
            prlog('%s<br>' % msg)

        product_name = self.product_name
        pr("Starting %(product_name)s install" % vars() )

        # Roles and Permissions ###(
        #
        self.verifyRoles((
            # A role that can manage the University.
            'UniversityManager',
            # A role that can manage the StudentsRecords.
            'StudentManager',
            # A role that can manage a Faculty.
            'FacultyManager',
            # A role that can manage a department.
            'DepartmentManager',
            # A role that can manage a Course.
            'CourseManager',
            # The Student Role
            'Student',
        ))
        waeup_perms = {
            UniversityManage:
                ('Manager', 'SectionManager','UniversityManager',
                 ),
            StudentManage:
                ('Manager', 'SectionManager','UniversityManager', 'StudentManager'
                 ),
            FacultyManage:
                ('Manager', 'SectionManager','UniversityManager', 'FacultyManager'
                 ),
            DepartmentManage:
                ('Manager', 'SectionManager','UniversityManager', 'DepartmentManager'
                 ),
            CourseManage:
                ('Manager', 'SectionManager','UniversityManager', 'CourseManager'
                 ),
        }
        self.setupPortalPermissions(waeup_perms)
        ###)

        # external methods ###(
        #
        ext_methods = ( { 'id': 'waeup_migrate',
                          'title': 'WAeUP (migrate from an earlier version)',
                          'script': 'WAeUP.install',
                          'method': 'migrate',
                          'protected': 1,
                        },
                      )
        portal_objectIds = portal.objectIds()
        for meth in ext_methods:
            method = meth['id']
            if method in portal_objectIds:
                portal._delObject(method)
            pr('Creating %s External Method' % method)
            ext_method = ExternalMethod(method,
                                        meth['title'],
                                        meth['script'],
                                        meth['method'])
            portal._setObject(method, ext_method)
            if method in portal_objectIds:
                manage_perms = portal[method].manage_permission
                if meth['protected']:
                    pr("Protecting %s" % method)
                    manage_perms(View, roles=['Manager'], acquire=0)
                    manage_perms(AccessContentsInformation, roles=['Manager'], acquire=0)
                else:
                    manage_perms(View, roles=['Manager'], acquire=1)
        ###)

        ##########################################
        # Actions
        ##########################################
        waeup_ptypes = "'University','StudentsFolder','Student','Jamb','Faculty','Department','Course'"
        waeup_ptypes += ",'AccoFolder','Accommodation','StudentPersonal','AcademicsFolder'"
        waeup_ptypes += ",'StudyLevel','Semester','CourseTicket','StudentDocuments','StudentEligibility'"
        if CPSSubscriptions: ###(

            ptypes = "('Portal', 'CPSMailAccess Message', 'CPSMailAccess Box', 'CPSMailAccess Folder',"\
                     + waeup_ptypes + ")"
            condition = "object.portal_type not in %s" % ptypes

            action = {'id' : 'notify_content',
                      'name' : 'action_notify_content',
                      'action' : 'string:${object_url}/content_notify_email_form',
                      'condition' : 'python:%s' % condition,
                      'permission' :  (CanNotifyContent,),
                      'category' : 'object',
                      }
            self.deleteActions({'portal_subscriptions': ['notify_content',]})
            self.verifyAction('portal_subscriptions', **action)
        if CPSForum:
            condition = "object.portal_type not in (%s)" % waeup_ptypes

            action = {'id' : 'activate_comments',
                      'name': 'action_activate_comments',
                      'action': 'string:${object/absolute_url}/set_comment_mode?mode=1',
                      'condition' : 'python:%s' % condition,
                      'permission': (ForumManageComments,),
                      'category' : 'object',
                      }
            self.deleteActions({'portal_subscriptions': ['activate_comments',]})
            self.verifyAction('portal_subscriptions', **action)
            # now portal_discussion
            self.deleteActions({'portal_discussion': ['comment',
                                                      'activate_comments',
                                                      'deactivate_comments',
                                                      'manage_comments']})
            action = {'id' : 'comment',
                      'name': 'action_comment',
                      'action': "string:${object/absolute_url}/post_comment",
                      'condition' : "python:getattr(object.getContent(), 'allow_discussion' , None) and object.hasCommentAction()",
                      'permission': (View,),
                      'category' : 'object',
                      }
            self.verifyAction('portal_discussion', **action)
            action = {'id' : 'activate_comments',
                      'name': 'action_activate_comments',
                      'action': "string:${object/absolute_url}/set_comment_mode?mode=1",
                      'condition' : "python:getattr(object.getTypeInfo(),'cps_proxy_type','') in ('document', 'folderishdocument') and getattr(object.getContent(), 'allow_discussion' , None) == 1",
                      'permission': (ForumManageComments,),
                      'category' : 'object',
                      }
            self.verifyAction('portal_discussion', **action)
            action = {'id' : 'deactivate_comments',
                      'name': 'action_deactivate_comments',
                      'action': "string:${object/absolute_url}/set_comment_mode?mode=0",
                      'condition' : "python:getattr(object.getTypeInfo(),'cps_proxy_type','') in ('document', 'folderishdocument') and getattr(object.getContent(), 'allow_discussion' , None) == 1",
                      'permission': (ForumManageComments,),
                      'category' : 'object',
                      }
            self.verifyAction('portal_discussion', **action)
            action = {'id' : 'manage_comments',
                      'name': 'action_manage_comments',
                      'action': "string:${object/absolute_url}/manage_comment",
                      'condition' : "python:getattr(object.getTypeInfo(),'cps_proxy_type','') in ('document', 'folderishdocument') and getattr(object.getContent(), 'allow_discussion' , None) == 1",
                      'permission': (ForumManageComments,),
                      'category' : 'object',
                      }
            self.verifyAction('portal_discussion', **action)

###)

        ##########################################
        # main_tab actions ###(
        ##########################################
        path = "/sections/%(SRPP_ID)s" % globals()
        actions = ( { 'tool'      : 'portal_actions',
                        'id'        : 'student_administration',
                        'name'      : 'Students',
                        'action'    : "python: portal.portal_url.getUrlFromRpath('sections/demouni/students')",
                        #'action'    : 'string:$portal_url%(path)s/students' % vars(),
                        'permission': (View, ),
                        'category'  : 'main_tabs',
                        'visible'   : 1,
                      },
                      { 'tool'      : 'portal_actions',
                        'id'        : 'academics',
                        'name'      : 'Academics',
                        'action'    : "python: portal.portal_url.getUrlFromRpath('sections/demouni/academics')",
                        #'action'    : 'string:${portal_url}/academics',
                        'permission': (UniversityManage),
                        'category'  : 'main_tabs',
                        'visible'   : 1,
                      },
                      { 'tool'      : 'portal_actions',
                        'id'        : 'accomodation',
                        'name'      : 'Accommodation',
                        'action'    : "python: portal.portal_url.getUrlFromRpath('sections/demouni/accommodation')",
                        #'action'    : 'string:${portal_url}/accommodation',
                        'permissions': (UniversityManage),
                        #'permissions': (ModifyPortalContent,UniversityManage,StudentManage),
                        'category'  : 'main_tabs',
                        'visible'   : 1,
                      },
                      { 'tool'      : 'portal_actions',
                        'id'        : 'chat',
                        'name'      : 'Chat',
                        'action'    : "python: portal.portal_url.getUrlFromRpath('sections/demouni/chat')",
                        #'action'    : 'string:${portal_url}/accommodation',
                        'permissions': (View),
                        #'permissions': (ModifyPortalContent,UniversityManage,StudentManage),
                        'category'  : 'main_tabs',
                        'visible'   : 1,
                      },
##                      { 'tool'      : 'portal_actions', ###(
##                        'id'        : 'add_jamb',
##                        'name'      : 'Add Student JAMB',
##                        'action'    : 'string:${object/absolute_url}/create_jamb',
##                        'permission': (),
##                        'condition' : 'python: member and here.portal_type in ("StudentsFolder",) and "StudentManager" in member.getGroups()',
##                        'category'  : 'student',
##                        'visible'   : 1,
##                      },
##                      { 'tool'      : 'portal_actions',
##                        'id'        : 'add_faculty',
##                        'name'      : 'Add New Faculty',
##                        'action'    : 'string:${object/absolute_url}/addFaculty',
##                        'permission': (),
##                        'condition' : 'python: member and here.portal_type in ("University",) and "StudentManager" in member.getGroups()',
##                        'category'  : 'student',
##                        'visible'   : 1,
##                      },
##                      { 'tool'      : 'portal_actions',
##                        'id'        : 'add_department',
##                        'name'      : 'Add New Department',
##                        'action'    : 'string:${object/absolute_url}/addDepartment',
##                        'permission': (),
##                        'condition' : 'python: member and here.portal_type in ("Faculty",) and "StudentManager" in member.getGroups()',
##                        'category'  : 'student',
##                        'visible'   : 1,
##                      },
##                      { 'tool'      : 'portal_actions',
##                        'id'        : 'add_course',
##                        'name'      : 'Add New Course',
##                        'action'    : 'string:${object/absolute_url}/addCourse',
##                        'permission': (),
##                        'condition' : 'python: member and here.portal_type in ("Department",) and "StudentManager" in member.getGroups()',
##                        'category'  : 'student',
##                        'visible'   : 1,
##                      },
##                      { 'tool'      : 'portal_actions',
##                        'id'        : 'add_personal',
##                        'name'      : 'Add personal Data',
##                        'action'    : 'string:${object/absolute_url}/create_personal_form',
##                        'permission': (),
##                        'condition' : 'python: 0 and member and not here.portal_type in ("Jamb","StudentsFolder") and not "StudentManager" in member.getGroups()',
##                        'category'  : 'student',
##                        'visible'   : 1,
##                      },
##                      { 'tool'      : 'portal_actions',
##                        'id'        : 'edit_jamb',
##                        'name'      : 'Edit Jamb Data',
##                        'action'    : 'cpsdocument_edit_form',
##                        'permission': ( ),
##                        'condition' : 'python: member and here.portal_type in ("Student",) and "StudentManager" in member.getGroups()',
##                        'category'  : 'student',
##                        'visible'   : 1,
##                      },
###)

                    )
        self.deleteActions({'portal_actions': [action['id'] for action in actions]})
        self.verifyActions(actions)
        ##########################################
###)

        # skins
        ##########################################
        pr("Verifying %(product_name)s skinss" % vars())
        wskins = { 'waeup_default' : 'Products/WAeUP/skins/waeup_default',
                   'waeup_faculty' : 'Products/WAeUP/skins/waeup_faculty',
                   'waeup_student' : 'Products/WAeUP/skins/waeup_student',
                 }
        self.verifySkins(wskins)
        self.resetSkinCache()

        # Themes ###(
        #
        # Importing portal themes
##        theme_container = getattr(portal, 'portal_themes')
##            # the first theme in each category is the default theme.
##        themes_list = {'WAeUP':    ({'id': 'waeup_plain_theme',
##                                  'file': 'waeup_plain_theme.zexp',
##                                  },
##                                  {'id': 'waeup_management_theme',
##                                   'file': 'waeup_management_theme.zexp',
##                                  },
##                                 ),
##                      }
##
##
##        theme_ids = theme_container.objectIds()
##        theme_container.manage_delObjects(theme_ids)
##        target_themes = themes_list[Target]
##        for theme in target_themes:
##            pr(" Importing %s theme" % theme['id'])
##            zexppath = os.path.join(zexpdir, theme['file'])
##            try:
##                theme_container._importObjectFromFile(zexppath)
##            except:
##                pr("    Could not import theme  %s" % theme['id'])
##
##        # set the first theme in the list as the default one.
##        theme_container.setDefaultTheme(target_themes[0]['id'])
###)


        ##########################################
        # portal types
        ##########################################
        dtypes = portal.getWAeUPTypes()
        self.verifyFlexibleTypes(dtypes)
        self.allowContentTypes('University', ('Workspace','Section',))
        ##########################################
        # Schemas
        ##########################################
        pr("Verifying %(product_name)s schemas" % vars())
        self.verifySchemas(portal.getWAeUPSchemas())
        ##########################################
        # widgets
        ##########################################
        pr("Verifying %(product_name)s widgets" % vars())
        self.verifyWidgets(portal.getWAeUPWidgets())
        ##########################################
        # layouts
        ##########################################
        pr("Verifying %(product_name)s layouts" % vars())
        self.verifyLayouts(portal.getWAeUPLayouts())
        ##########################################
        # Vocabularies
        ##########################################
        pr("Verifying %(product_name)s vocabularies" % vars())
        self.verifyVocabularies(portal.getWAeUPVocabularies())
        ##########################################
        # Groups
        ##########################################

        self.installCustomWorkflows()
        self.verifyWorkflowAssociation()

        pr("End of specific %(product_name)s install" % vars())
        #return '\n'.join(log)
        self.finalize()


    def verifyPortlets(self, portlets=(), object=None): ###(
        """Verify the existence of given portet in the object's portlet
        container. If not found, a portlet is instantiated.
        Existing portlets are not affected.

        'portlets' is a tuple with the dictionaries given by the export tab
        as entries.
        The default object is the portal itself.

        return the list a new portlet ids.
        """

        if object is None:
            object = self.portal

        self.log('Verifying portlets on %s' % object.absolute_url(relative=1))

        portlet_container = self.getPortletContainer(object, create=1)

        ttool = self.getTool('portal_types')

        returned = []
        for new_portlet in portlets:
            existing_portlets = portlet_container.listPortlets()
            updated = 0

            # Check if the portlet needs an update
            identifier = new_portlet.get('identifier')
            if identifier:
                for portlet in existing_portlets:
                    if identifier == portlet.identifier:
                        self.log(" Update of portlet: %s" % portlet)
                        portlet.edit(**new_portlet)
                        portlet_id = portlet.getId()
                        updated = 1
                        continue
            slot = new_portlet.get('slot')
            if slot:
                for portlet in existing_portlets:
                    if slot == portlet.slot:
                        self.log(" Update of portlet: %s" % portlet)
                        portlet.edit(**new_portlet)
                        portlet_id = portlet.getId()
                        updated = 1
                        continue

            if not updated:
                self.log("   Creation of portlet: %s" % new_portlet)
                portlet_id = self.portal.portal_cpsportlets.createPortlet(
                    ptype_id=new_portlet['type'],
                    context=object,
                    **new_portlet)
            if portlet_id not in returned:
                returned.append(portlet_id)
        return returned
    ###)

    def installCustomWorkflows(self): ###(
        """Installs custom workflows
        """
        from Products.WAeUP.Workflows.WAeUPWorkflow import \
             waeupWorkflowsInstall

        waeupWorkflowsInstall(self.context)

###)

    def verifyWorkflowAssociation(self): ###(
        """Verify workflow association
        """
        ws_chains = {
                      'Student': 'waeup_workspace_wf',
                      'Jamb': 'waeup_workspace_wf',
                      }

        se_chains = { 'University': 'waeup_section_wf',
                      'AcademicsFolder': 'waeup_section_wf',
                      'StudentsFolder': 'waeup_student_wf',
                      'Student': 'waeup_student_wf',
                      'StudentPersonal': 'waeup_student_wf',
                      'StudentEligibility': 'waeup_student_wf',
                      'StudentDocuments': 'waeup_student_wf',
                      'Jamb': 'waeup_section_wf',
                      'ScratchCard': 'waeup_section_wf',
                      'Faculty': 'waeup_section_wf',
                      'Department': 'waeup_section_wf',
                      'Course': 'waeup_section_wf',
                      'StudyLevel': 'waeup_student_wf',
                      'Semester': 'waeup_student_wf',
                      'CourseTicket': 'waeup_student_wf',
                      'AccoFolder': 'waeup_section_wf',
                      'Accommodation': 'waeup_section_wf',
                      }

        self.verifyLocalWorkflowChains(self.portal['workspaces'],
                                       ws_chains,
                                       destructive=1)
        self.verifyLocalWorkflowChains(self.portal['sections'],
                                       se_chains,
                                       destructive=1)
    ###)

    def verifyFaculties(self, academics): ###(
        """install Universityspecific Faculies with Departments"""
        faculties = [
##                     {'id': 'agri', ###(
##                      'Title': 'Agriculture',
##                      'departments': [
##                                     { 'id': 'dep1', ###(
##                                       'Title': 'One',
##                                     },
##                                     ],
##                      },###)
                      { 'id': 'science',
                      'Title': 'Science',
                      'departments': [
                                     { 'id': 'bio', ###(
                                       'Title': 'Biochemistry',
                                     },
                                     { 'id': 'bot',
                                       'Title': 'Botany',
                                     },
                                     { 'id': 'che',
                                       'Title': 'Chemistry',
                                     },
                                     { 'id': 'com',
                                       'Title': 'Computer Science',
                                     },
                                     { 'id': 'geo',
                                       'Title': 'Geologie',
                                     },
                                     { 'id': 'mat',
                                       'Title': 'Mathematics',
                                     },
                                     { 'id': 'mic',
                                       'Title': 'Microbiology',
                                     },
                                     { 'id': 'opt',
                                       'Title': 'Optometry',
                                     },
                                     { 'id': 'phy',
                                       'Title': 'Physics',
                                     },
                                     { 'id': 'zoo',
                                       'Title': 'Zoology',
                                     },
                                     ],
                      },###)
                     ]###)
        self.log('Verifying Faculties in %s' % academics.absolute_url(relative=1))
        for faculty in faculties:
            fid = faculty['id']
            f = getattr(academics,fid,None)
            self.log('Checking Faculty %(id)s = %(Title)s' % faculty)
            if f is None:
                self.log('Creating Faculty %(id)s = %(Title)s' % faculty)
                academics.invokeFactory('Faculty', fid)
                f = getattr(academics,fid)
                f.getContent().edit(mapping=faculty)
            for department in faculty['departments']:
                self.log('Checking Department %(id)s = %(Title)s' % department)
                did = department['id']
                d = getattr(f,did,None)
                if d is None:
                    self.log('Creating Department %(id)s = %(Title)s' % department)
                    f.invokeFactory('Department', did)
                    d = getattr(f,did)
                    d.getContent().edit(mapping=department)
    ###)



def install(self): ###(
    installer = WAeUPInstaller(self)
    installer.install(self)
    dirtool = getattr(self,'portal_directories')
    groups = dirtool.groups
    for delEntry in ('StudentManager',):
        if delEntry in groups.listEntryIds():
            groups.deleteEntry(delEntry)
    for newEntry in ('Students',):
        if newEntry not in groups.listEntryIds():
            groups.createEntry({'group': newEntry,
                                'members': []})
    #groups.manage_setLocalGroupRoles(groupid = 'StudentManager',roles=('Manager',))
    #groups.manage_setLocalGroupRoles(groupid = 'Students',roles=('Contributor',))
    sections = getattr(self,'sections')
    waeup = getattr(sections,SRPP_ID,None)
    if not waeup:
        sections.invokeFactory('University',SRPP_ID)
        waeup = getattr(sections,SRPP_ID)
        waeup.getContent().edit(mapping={'Title':SRPP_TITLE})
        waeup.folder_localrole_add(member_ids=('group:Students',),
                                            member_role='SectionReviewer',
                                            )
        waeup.invokeFactory('StudentsFolder','students')
        students = getattr(waeup,'students').getContent()
        students.edit(mapping={'Title':'Students'})
        waeup.folder_localrole_add(member_ids=('group:Students',),
                                            member_role='SectionReviewer',
                                            )
##        waeup.content_create(type_name='AcademicsFolder',title='academics')
##        sections.waeup.folder_localrole_add(member_ids=('group:StudentManager',),
##                                            member_role='SectionManager',
##                                            )
        waeup.students.manage_setLocalGroupRoles(groupid = 'Students',roles=('Contributor',))
        waeup.invokeFactory('AcademicsFolder','academics', title='Academics')
        academics = getattr(waeup,'academics').getContent()
        academics.edit(mapping={'Title':'Academics'})
        waeup.invokeFactory('AccoFolder','accommodation', title='Accommodation')
        accommodation = getattr(waeup,'accommodation').getContent()
        accommodation.edit(mapping={'Title':'Accommodation'})
    academics = getattr(waeup,'academics',None)
    if academics is None:
        waeup.invokeFactory('AcademicsFolder','academics')
        academics = getattr(waeup,'academics')
        academics.getContent().edit(mapping={'Title':'Academics'})
    installer.verifyFaculties(academics)
    if not hasattr(waeup,'accommodation'):
        waeup.invokeFactory('AccoFolder','accommodation')
        accommodation = getattr(waeup,'accommodation').getContent()
        accommodation.edit(mapping={'Title':'Accommodation'})
    waeup.manage_setLocalGroupRoles(groupid = 'role:Anonymous',roles=('SectionReader',))
    # portlets ###(
    #
    portlets = (
##              {'identifier': 'waeup_main_tabs',
##              'type': 'Custom Portlet',
##              'slot': 'main_tabs',
##              'order': 0,
##              'render_method': 'portlet_main_navigation',
##              'Title': 'main tabs',
##              },
              {#'identifier': 'waeup_breadcrumbs',
              'type': 'Breadcrumbs Portlet',
              'slot': 'waeup_breadcrumbs',
              'first_item': 0,
              'display_site_root': 0,
              'Title': 'waeup_breadcrumbs',
              'display': 'horizontal_trail',
              'display_hidden_folders': 0,
              'order': 0,
              },
              {#'identifier': 'waeup_main_tab_actions',
              'type': 'Actions Portlet',
              'slot': 'main_tabs',
              'order': 0,
              'categories': ['main_tabs',],
              'Title': 'waep_main_tab_actions',
              },
              {#'identifier': 'waeup_object_actions',
              'type': 'Actions Portlet',
              'slot': 'waeup_object_actions',
              'order': 0,
              'categories': ['object',],
              'Title': 'waep_manager_actions',
              },
              {#'identifier': 'waeup_left_top',
              'type': 'Custom Portlet',
              'slot': 'left_top',
              'order': 0,
              'render_method': 'portlet_session_info',
              'Title': 'Session Info',
              },
            )
    installer.verifyPortletContainer(waeup)
    installer.verifyPortlets(portlets,waeup)

###)
    return installer.logResult()
    ###)

def migrate(self): ###(
    "update data"
    log = []
    prlog = log.append

    def pr(msg, prlog=prlog):
        prlog('%s' % msg)

    sections = getattr(self,'sections')
    waeup = getattr(sections,SRPP_ID,None)
    pr( "Start migrate")
    pr("migrating Students")
    students = getattr(waeup,'students')
    pr("migrating courses")
    academics = getattr(waeup,'academics')
    for fac in [getattr(academics,f.id) for f in academics.contentValues(filter={'portal_type': ('Faculty',)})]:
        pr("Faculty: %s" % fac.title_or_id())
        for dep in [getattr(fac,d.id) for d in fac.contentValues(filter={'portal_type': ('Department',)})]:
            pr("Department: %s" % dep.title_or_id())
            for course in [getattr(dep,c.id) for c in dep.contentValues(filter={'portal_type': ('Course',)})]:
                pr("Course: %s" % course.title_or_id())
                content = course.getContent()
                heading = getattr(content,'heading',course.id)
                pr("heading = %(heading)s" % vars())
                content.edit(mapping={'Title': heading})
    pr("migrating halls")
    for ac in [getattr(waeup,a.id) for a in waeup.contentValues(filter={'portal_type': ('AccoFolder',)})]:
        for hall in [getattr(ac,h.id) for h in ac.contentValues(filter={'portal_type': ('Accommodation',)})]:
            pr("Hall: %s" % hall.title_or_id())
            content = hall.getContent()
            heading = getattr(content,'heading',hall.id)
            pr("heading = %(heading)s" % vars())
            content.edit(mapping={'Title': heading})
    return '\n'.join(log)

###)

