################################################################
# vs.dashboardmanager
# (C) 2010, Veit Schiele & Andreas Jung
# Published under the GNU Public Licence V 2 (GPL 2)
################################################################

import operator 
from zope.component import getUtility, getMultiAdapter
try:
    from zope.app.container.interfaces import INameChooser # Plone < 4.3
except ImportError:
    from zope.container.interfaces import INameChooser # Plone >= 4.3
from Products.CMFCore.utils import getToolByName
from Products.CMFCore.interfaces import ISiteRoot
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile

from plone.portlets.interfaces import IPortletManager, IPortletAssignment, IPortletAssignmentMapping
from plone.app.portlets.utils import assignment_mapping_from_key

from vs.dashboardmanager import MF as _
from vs.dashboardmanager.logger import LOG

class Assignments(BrowserView):

    template = ViewPageTemplateFile('assignments.pt')

    def groups_for_js(self):
        """ Groups for Javascript """
        groups = self.getGroups()
        return str([group['id'] for group in groups])

    def getGroups(self): 
        """ Return PAS groups """
        search_view = self.context.restrictedTraverse('@@pas_search')
        if 'name' in self.request:
            # search by 'id' also seams to work through LDAP groups
            # instead of search by 'name'
            result = search_view.searchGroups(id=self.request.name)
        else:
            result = search_view.searchGroups()
        result = [r for r in result if not r['pluginid'] in ('auto_group',)]
        result = sorted(result, key=operator.itemgetter('title')) 
        return result

    def _get_memberids_from_request(self):
        """ Return a list of userids based on the 'group' and 'userid'
            parameters from the request.
        """

        userid = self.request.get('userid', '')
        group = self.request.get('group', '')

        gt = getToolByName(self.context, 'portal_groups')
        mt = getToolByName(self.context, 'portal_membership')

        if userid and group:
            return ()

        if not userid and not group:
            return ()

        site = getUtility(ISiteRoot)
        if userid:
            userids = [userid]
        else:
            acl = self.context.acl_users
            grp = acl.getGroupById(group)
            userids = grp.getMemberIds()

        return userids


    def push_assignment(self):
        """ Push all assignment portlet page assignment into the
            dashboard of a user or a group of users.
        """

        userids = self._get_memberids_from_request()
        if not userids:
            self.context.plone_utils.addPortalMessage(u'No members found', 'error')
            url = '%s/@@assignments?userid=%s&group=%s' % (self.context.absolute_url(),
                    self.request.get('userid', ''), self.request.get('group', ''))
            return self.request.response.redirect(url)

        dashboards_updated = dict()
        site = getUtility(ISiteRoot)
        for userid in userids:

            # iterate over all configured portlet managers (1-4) for PortletPage
            for i in range(1, 5):

                manager_name = 'vs.dashboardmanager.column%d' % i
                manager = getUtility(IPortletManager, name=manager_name, context= self.context)
                mapping = getMultiAdapter((self.context, manager), IPortletAssignmentMapping)

                # get hold of the user dashboard manager
                manager2 = getUtility(IPortletManager, name='plone.dashboard%d' % i)
                mapping2 = assignment_mapping_from_key(site, 
                                                      'plone.dashboard%d' % i, 
                                                       category='user', 
                                                       key=userid, 
                                                       create=True)

                ids2 = [tp[0] for tp in mapping2.items()]

                # and copy over the assignments
                for id, assignment in mapping.items():
                    assignment_copy=assignment._getCopy(assignment)
                    if not id in ids2:
                        mapping2[id] = assignment_copy
                        LOG.info('assigned portlet %s to %s' % (id, userid))
                        dashboards_updated[userid] = True

        if dashboards_updated:
            self.context.plone_utils.addPortalMessage(u'Dashboard(s) updated for members: %s' 
                                                      % ', '.join(dashboards_updated.keys()))
        else:
            self.context.plone_utils.addPortalMessage(u'No dashboards updated')
        return self.request.response.redirect(self.context.absolute_url())


    def remove_assignments(self):
        """ Remove a list of portlets from user dashboards """

        site = getUtility(ISiteRoot)
        for id in self.request.form.get('ids', []):
            # id = 'user=XXXX::manager=YYYY:portlet=ZZZZ'
            items = id.split('::')
            userid = items[0].split('=')[-1]
            portlet_manager_name = items[1].split('=')[-1]
            portlet_id = items[2].split('=')[-1]

            # get hold of the user dashboard manager
            portlet_manager = getUtility(IPortletManager, name=portlet_manager_name)
            mapping = assignment_mapping_from_key(site, 
                                                  portlet_manager_name,
                                                  category='user', 
                                                  key=userid, 
                                                  create=False)
            del mapping[portlet_id]
            mapping._p_changed = True

        self.context.plone_utils.addPortalMessage((u'label_portlets_removed_from_dashboard',
                                                    u'Portlets removed from user dashboard(s)'))

        url = '%s/@@view-assignments?userid=%s&group=%s' % (self.context.absolute_url(),
                self.request.get('userid', ''), self.request.get('group', ''))
        return self.request.response.redirect(url)

    def __call__(self, *args, **kw):
        return self.template(*args, **kw)


class ViewAssignments(Assignments):

    template = ViewPageTemplateFile('view-assignments.pt')

    def get_assignments(self):
        """ Return dashboard settings for a given group or a user """

        userids = self._get_memberids_from_request()
        site = getUtility(ISiteRoot)

        user2dash = list()
        for userid in userids:
            # iterate over the four portlet managers in each user dashboard
            dash2portlets = list()
            found = False
            for i in range(1, 5):
                # get hold of the user dashboard manager
                manager_name = 'plone.dashboard%d' % i
                manager = getUtility(IPortletManager, name=manager_name)
                mapping = assignment_mapping_from_key(site, 
                                                      manager_name,
                                                      category='user', 
                                                      key=userid, 
                                                      create=True)
                portlets = list()
                for portlet_id in mapping:
                    assignment = mapping[portlet_id]
                    parameters = dict([(k,v) for k,v in assignment.__dict__.items() if not k.startswith('_')])
                    portlets.append(dict(portlet_id=portlet_id, 
                                         assignment=assignment,
                                         parameters=parameters))
                    found = True

                dash2portlets.append(dict(manager=manager_name, portlets=portlets))
            user2dash.append(dict(userid=userid, dashboards=dash2portlets, hasDashboard=found))

        return user2dash
