# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - Automaticaly subscribe user(s) on save

    <<SubscribeTo(UserName1[,+GroupName1[,-UserName2]])>>

    Will add those users and/or group of users as subscribers while saving the
    page. These users are not subscribed for templates nor while preview the
    page. To subscribe to this template the FQTN (full-qualified template name)
    has to be specified as one of the parameters.

    Using (-) and (+) it's possible to create a flexible list of users will
    be subscribed to this page. E.g. select a long group and remove with (-)
    some group members. Or select a short group and extend the list by adding
    (+) additional users. By default users are added if no (-) or (+) is
    specified. (-) does not remove the subscribtion for the specified user.
    (-) does not change the status of the subscription for the specified user.

    @copyright: (C) 2005,2006  Raphael Bossek
    @license: GNU GPL 2, see COPYING for details
    @version: 20060402
    @url: http://www.solutions4linux.de/cgi-bin/view/Main/MoinMoinSubscribeTo
"""

from MoinMoin import user
import re

def execute (macro, args):
	_ = macro.request.getText

	# return immediately if getting links for the current page
	if macro.request.mode_getpagelinks:
		return ''

	unknownuname = {}
	missingemail = {}
	outofdateversion = 0
	result = u''
	allusers = re.split (r'[,;\s]+', args)
	subscribeto = {}
	page_name = macro.request.page.page_name
	is_preview = macro.form.has_key ('button_preview')
	p_warning = u'<p class="warning" style="margin: 0; padding: 0.4em; background: #FFFF80">' + macro.formatter.icon ("info") + u' '
	p_notice = u'<p class="notice" style="margin: 0; padding: 0.4em; background: #81BBF2">' + macro.formatter.icon ("info") + u' '
	p_info = u'<p class="info" style="margin: 0; padding: 0.4em; background: #E6EAF0">' + macro.formatter.icon ("info") + u' '
	# TODO: Should be compiled only once, and cached in cfg
	group_re = re.compile (macro.cfg.page_group_regex, re.UNICODE)
	# By default templates are not subsribed. This can be changed by
	# specifing the FQTN as parameter.
	is_template = re.search (macro.cfg.page_template_regex, page_name, re.UNICODE)
	# Proceed the list in the same order as specified by the user.
	# This allow us to work with groups and users in the same way
	# as specifing all members of a group.
	for uname in allusers:
		# Skip empty names
		if not uname:
			continue
		# Determine what to do with the user/group members.
		if uname[:1] == '-':
			uname = uname[1:]
			remove_action = True
		else:
			if uname[:1] == '+':
				uname = uname[1:]
			remove_action = False

		# It's a special feature. If the FQTN (full-qualified template name)
		# is one of the parameters we allow to subscribe to this template too.
		if remove_action == False and uname == page_name:
			is_template = False
			continue

		members = []
		# Distinguish between user and group. Create a list of
		# users which has to be subscribed to.
		if group_re.search (uname):
			# Recursively expand groups
			groupdict = macro.request.dicts
			if groupdict.hasgroup (uname):
				members = groupdict.members (uname)
			else:
				unknownuname[uname] = 1
		else:
			members = [uname]

		# Go through all members and proceed with the same action.
		for uname in members:
			uid = user.getUserId (macro.request, uname)
			if not uid:
				# Only if this user has to be added and does not exists put
				# his name in our unknwonuname list. Otherwise the use does
				# not matter.
				if remove_action == False:
					unknownuname[uname] = 1
				# If this user was added before but we know now that should
				# be skipped we update the unknownuname list afterward.
				else:
					if uname in subscribeto:
						del subscribeto[uname]
					if uname in unknownuname:
						del unknownuname[uname]
			else:
				thisuser = user.User (macro.request, id = uid)
				if not thisuser.email:
					missingemail[uname] = 1
				else:
					subscribeto[uname] = (thisuser, remove_action)
				# MoinMoin compatibility check
				if not 'subscribePage' in dir (thisuser) and not 'subscribe' in dir (thisuser):
					outofdateversion = 1
					break
	if not outofdateversion:
		if unknownuname:
			result += p_warning + _(u'This user(s)/group(s) are unknown by now: %s') % u', '.join (unknownuname.keys()) + u'</p>'
		if missingemail:
			result += p_warning + _(u'Follwing users(s) missing an email address in their profile: %s') % u', '.join (missingemail.keys()) + u'</p>'
		if subscribeto:
			addeduname = []
			faileduname = []
			subscribeduname = []
			subscribe_status = (1 == 1)
			if not is_template:
				for uname, (thisuser, remove_action) in subscribeto.iteritems():
					# Do not modify the subscribtion of this usser.
					if remove_action == True:
						continue
					# Do _not_ subscribe these users while preview the page
					if not thisuser.isSubscribedTo ([page_name]):
						if not is_preview:
							# Support for MoinMoin 1.3
							if 'subscribePage' in dir (thisuser):
								subscribe_status = thisuser.subscribePage (page_name)
								if subscribe_status:
									thisuser.save()
							# Support for MoinMoin 1.5
							elif 'subscribe' in dir (thisuser):
								subscribe_status = thisuser.subscribe (page_name)
							else:
								outofdateversion = 1
								break
						if not subscribe_status:
							faileduname.append (uname)
						else:
							addeduname.append (uname)
					else:
						subscribeduname.append (uname)
			else:
				result += p_notice + _(u'This template will not be subscribed!') + u' ' + _(u'Follwing user(s)/group(s) are remembered to be subscribed later with a regular page: %s') % u', '.join (subscribeto.keys()) + u'</p>'
			if addeduname:
				result += p_info + _(u'Following new user(s) will be subscribed to %s before saving: %s') % (page_name, u', '.join (addeduname)) + u'</p>'
			if subscribeduname:
				result += p_info + _(u'Following user(s) are already subsribed to %s: %s') % (page_name, u', '.join (subscribeduname)) + u'</p>'
			if faileduname:
				result += p_warning + _(u'This user(s) failed to subscribe to: %s') % u', '.join (faileduname) + u'</p>'

	if outofdateversion:
		result += p_warning + _(u'Sorry, out-of-date version of SubscribeTo marcro installed! Functionality disabled until an update occurs.') + u'</p>'

	if is_preview:
		return result
	return u''

