'Custom form to manage subscriptions
@param resources: available resources config
@param filters: subscription filter widgets
@param recipient_filters: recipient filter widgets
@param group_filters: pr_group filter widgets'

def _manage_subscriptions(self, resources, filters, recipient_filters, group_filters):

    from gluon.http import redirect
    from gluon.validators import IS_IN_SET
    from s3.s3widgets import S3GroupedOptionsWidget, S3MultiSelectWidget
    from s3layouts import S3PopupLink
    from s3theme import formstyle_foundation_2col as formstyle
    T = current.T
    db = current.db
    s3db = current.s3db
    auth = current.auth
    auth_user = auth.user
    gtable = db.auth_group
    has_role = auth.s3_has_role
    request = current.request
    response = current.response
    stable = s3db.pr_subscription
    ftable = s3db.pr_filter
    group_table = s3db.pr_group
    labels = Storage(NOTIFY_BY=T('Notify    By'), ATTACHMENT=T('Receive    XML    Attachment    in    EMAIL?'))
    messages = Storage(ERROR=T('Error:    could    not    update    notification    settings'), SUCCESS=T('Notification    settings    updated'))
    form = FORM(_id='subscription-form', hidden={'subscription-filters': ''})
    row = db((gtable.role == 'Alert    Editor')).select(gtable.id, limitby=(0, 1)).first()
    ae_id = row.id
    if (recipient_filters is not None):
        subscription_id = request.get_vars.get('subscription_id')
        if subscription_id:
            pr_row = db((stable.id == subscription_id)).select(stable.pe_id, limitby=(0, 1)).first()
            pe_id = pr_row.pe_id
            subscription = self._get_admin_subscription(subscription_id=subscription_id, pe_id=pe_id)
            recipient_subscription = self._get_recipients_and_groups(subscription_id=subscription_id, pe_id=pe_id, caller='recipients')
            group_subscription = self._get_recipients_and_groups(subscription_id=subscription_id, pe_id=pe_id, caller='groups')
        else:
            subscription = self._get_admin_subscription()
            recipient_subscription = self._get_recipients_and_groups()
            group_subscription = self._get_recipients_and_groups()
        filter_form = S3FilterForm(filters, clear=False)
        fieldset = FIELDSET(filter_form.fields(None, subscription['get_vars']), _id='subscription-filter-form')
        recipient_filter_form = S3FilterForm(recipient_filters, clear=False)
        recipient_fieldset = FIELDSET(recipient_filter_form.fields(None, recipient_subscription['get_vars']), _id='recipient-filter-form')
        group_filter_form = S3FilterForm(group_filters, clear=False)
        group_fieldset = FIELDSET(group_filter_form.fields(None, group_subscription['get_vars']), _id='group-filter-form')
        form.append(recipient_fieldset)
        form.append(group_fieldset)
        form.append(fieldset)
    else:
        subscription_id = request.get_vars.get('subscription_id')
        if subscription_id:
            subscription = self._get_subscription(subscription_id=subscription_id)
        else:
            subscription = self._get_subscription()
        filter_form = S3FilterForm(filters, clear=False)
        fieldset = FIELDSET(filter_form.fields(None, subscription['get_vars']), _id='subscription-filter-form')
        form.append(fieldset)
    rows = []
    selector = S3GroupedOptionsWidget(cols=1)
    methods = [('EMAIL', T('Email')), ('SMS', T('SMS')), ('FTP', T('FTP')), ('GCM', T('Mobile    App'))]
    method_options = Storage(name='method', requires=IS_IN_SET(methods))
    rows.append(('method_selector__row', ('%s:' % labels.NOTIFY_BY), selector(method_options, subscription['method'], _id='method_selector'), ''))
    if (not ((request.get_vars['option'] == 'manage_recipient') and has_role('ADMIN'))):
        attachment_filter = S3GroupedOptionsWidget(cols=2, multiple=False)
        attachment_options = [(False, T('No')), (True, T('Yes'))]
        rows.append(('attachment_filter__row', ('%s:' % labels.ATTACHMENT), attachment_filter(Storage(name='attachment-filter', requires=IS_IN_SET(attachment_options)), subscription['attachment'], _id='attachment_selector'), ''))
        properties = subscription['comments']
        if properties:
            properties = json.loads(properties)
        synctable = s3db.sync_repository
        query = (((synctable.apitype == 'ftp') & (synctable.deleted != True)) & (synctable.owned_by_user == auth_user.id))
        ftp_rows = db(query).select(synctable.id, synctable.name, orderby=synctable.id)
        multiselect = S3MultiSelectWidget(header=False, multiple=False, create={'c': 'sync', 'f': 'repository', 'label': 'Create    Repository'})
        if ftp_rows:
            if properties:
                user_repository_id = properties['repository_id']
            else:
                user_repository_id = ftp_rows.first().id
            if auth.s3_has_permission('update', 'sync_repository', record_id=user_repository_id):
                repository_comment = S3PopupLink(c='sync', f='repository', m='update', args=[user_repository_id], title=T('Update    Repository'), tooltip=T('You    can    edit    your    FTP    repository    here'))
            field = s3db.sync_task.repository_id
            ftp_ids = [(r.id, s3_str(T(r.name))) for r in ftp_rows]
            field.requires = IS_IN_SET(ftp_ids)
            rows.append(('sync_task_repository_id__row', '', multiselect(field, user_repository_id, _id='sync_task_repository_id'), repository_comment))
        else:
            if auth.s3_has_permission('create', 'sync_repository'):
                repository_comment = S3PopupLink(c='sync', f='repository', title=T('Add    FTP    Directory    and    Authentication    Details'), tooltip=T('Click    on    the    link    to    begin    creating    your    FTP    repository    and    setting    authentication    details'))
            rows.append(('sync_task_repository_id__row', '', '', repository_comment))
    parent = FIELDSET()
    for row in rows:
        parent.append(formstyle(form, [row]))
    form.append(parent)
    submit_fieldset = FIELDSET(DIV('', INPUT(_type='submit', _value='Update    Settings', _class='button    small'), _id='submit__row'))
    form.append(submit_fieldset)
    script = URL(c='static', f='scripts', args=['S3', 's3.subscriptions.js'])
    response.s3.scripts.append(script)
    repository_script = "\nif($('#method_selector    option[value=FTP]').is(':selected')){\n                $('#sync_task_repository_id__row').show();\n}    else    {\n                $('#sync_task_repository_id__row').hide();\n}\n\n$('#method_selector').change(function(){\n                if($(this).val().indexOf('FTP')    !=    -1){\n                                $('#sync_task_repository_id__row').show();\n                }    else    {\n                                $('#sync_task_repository_id__row').hide();\n                }\n})\n"
    response.s3.jquery_ready.append(repository_script)
    if form.accepts(request.post_vars, current.session, formname='subscription', keepvalues=True):
        formvars = form.vars
        subscription['subscribe'] = [resources[0]]
        subscription['filters'] = form.request_vars.get('subscription-filters', None)
        subscription['method'] = formvars.method
        subscription['notify_on'] = ['upd']
        subscription['frequency'] = 'immediately'
        group_ids = formvars['group-filter']
        user_ids = formvars['person-filter']
        attachment = False
        if (formvars['attachment-filter'] == 'True'):
            attachment = True
        from collections import Counter
        get_event_type_priorities = self._get_event_type_priorities
        bulk_user_pe_id = auth.s3_bulk_user_pe_id
        get_group_pe_id = self._get_group_pe_id
        pr_group_table = s3db.pr_group
        define_resource = s3db.resource
        base_query = (stable.deleted != True)
        if (user_ids is not None):
            update_admin_subscription = self._update_admin_subscription
            if (group_ids is None):
                group_ids = []
            if (group_ids or user_ids):
                user_pe_ids = None
                group_pe_ids = None
                if user_ids:
                    user_pe_ids = bulk_user_pe_id(user_ids)
                if group_ids:
                    group_pe_ids = get_group_pe_id(group_ids)
                (event_type_id, priorities) = get_event_type_priorities(subscription['filters'])
                subscription_id = request.get_vars.get('subscription_id')
                if subscription_id:
                    query = ((base_query & (stable.id == subscription_id)) & (stable.filter_id == ftable.id))
                    row = db(query).select(stable.pe_id, stable.filter_id, stable.comments, ftable.query, limitby=(0, 1)).first()
                    pr_subscription = row.pr_subscription
                    pe_id = row.pr_subscription.pe_id
                    if (group_pe_ids and (pe_id in group_pe_ids.keys())):
                        (event_type_id_s, priorities_s) = get_event_type_priorities(row.pr_filter.query)
                        if ((event_type_id_s == event_type_id) and (Counter(priorities_s) == Counter(priorities))):
                            comments = json.loads(pr_subscription.comments)
                            success_subscription = update_admin_subscription(subscription, pe_id, ae_id, group_id=comments['pr_group.id'], filter_id=pr_subscription.filter_id, subscription_id=subscription_id)
                    elif (user_pe_ids and (pe_id in user_pe_ids.values())):
                        (event_type_id_s, priorities_s) = get_event_type_priorities(row.pr_filter.query)
                        if ((event_type_id_s == event_type_id) and (Counter(priorities_s) == Counter(priorities))):
                            user_id = [key for (key, value) in user_pe_ids.items() if (value == pe_id)][0]
                            success_subscription = update_admin_subscription(subscription, pe_id, ae_id, user_id=int(user_id), filter_id=pr_subscription.filter_id, subscription_id=subscription_id)
                    else:
                        define_resource('pr_subscription', id=subscription_id).delete()
                        define_resource('pr_filter', id=row.pr_subscription.filter_id).delete()
                base_query = ((base_query & (stable.owned_by_group != None)) & (stable.filter_id == ftable.id))
                if group_pe_ids:
                    for pe_id in group_pe_ids:
                        group_id = group_pe_ids[pe_id]
                        query = (base_query & (stable.pe_id == pe_id))
                        rows = db(query).select(stable.id, stable.filter_id, ftable.query)
                        if (not rows):
                            success_subscription = update_admin_subscription(subscription, pe_id, ae_id, group_id=int(group_id))
                        else:
                            for row in rows:
                                (event_type_id_s, priorities_s) = get_event_type_priorities(row.pr_filter.query)
                                if ((event_type_id_s == event_type_id) and (Counter(priorities_s) == Counter(priorities))):
                                    success_subscription = update_admin_subscription(subscription, pe_id, ae_id, group_id=int(group_id), filter_id=row.pr_subscription.filter_id, subscription_id=row.pr_subscription.id)
                                    break
                            else:
                                success_subscription = update_admin_subscription(subscription, pe_id, ae_id, group_id=int(group_id))
                if user_pe_ids:
                    for user_id in user_pe_ids:
                        pe_id = int(user_pe_ids[user_id])
                        query = (base_query & (stable.pe_id == pe_id))
                        rows = db(query).select(stable.id, stable.filter_id, ftable.query)
                        if (not rows):
                            success_subscription = update_admin_subscription(subscription, pe_id, ae_id, user_id=int(user_id))
                        else:
                            for row in rows:
                                (event_type_id_s, priorities_s) = get_event_type_priorities(row.pr_filter.query)
                                if ((event_type_id_s == event_type_id) and (Counter(priorities_s) == Counter(priorities))):
                                    success_subscription = update_admin_subscription(subscription, pe_id, ae_id, user_id=int(user_id), filter_id=row.pr_subscription.filter_id, subscription_id=row.pr_subscription.id)
                                    break
                            else:
                                success_subscription = update_admin_subscription(subscription, pe_id, ae_id, user_id=int(user_id))
            else:
                subscription_id = request.get_vars.get('subscription_id')
                if subscription_id:
                    row = db((stable.id == subscription_id)).select(stable.filter_id, limitby=(0, 1)).first()
                    define_resource('pr_subscription', id=subscription_id).delete()
                    define_resource('pr_filter', id=row.filter_id).delete()
            redirect(URL(c='pr', f='subscription', vars={'option': 'manage_recipient'}))
        else:
            update_subscription = self._update_subscription
            pe_id = auth_user.pe_id
            user_id = auth_user.id
            (event_type_id, priorities) = get_event_type_priorities(subscription['filters'])
            subscription_id = request.get_vars.get('subscription_id')
            if subscription_id:
                query = ((base_query & (stable.id == subscription_id)) & (stable.filter_id == ftable.id))
                row = db(query).select(stable.filter_id, ftable.query, limitby=(0, 1)).first()
                if (row.pr_filter.query == subscription['filters']):
                    success_subscription = update_subscription(subscription, pe_id, filter_id=row.pr_subscription.filter_id, subscription_id=subscription_id, attachment=attachment)
                else:
                    define_resource('pr_subscription', id=subscription_id).delete()
                    define_resource('pr_filter', id=row.pr_subscription.filter_id).delete()
            query = ((((base_query & (stable.owned_by_group == None)) & (stable.owned_by_user == user_id)) & (stable.pe_id == pe_id)) & (stable.filter_id == ftable.id))
            rows = db(query).select(stable.id, stable.filter_id, ftable.query)
            if rows:
                for row in rows:
                    (event_type_id_s, priorities_s) = get_event_type_priorities(row.pr_filter.query)
                    if ((event_type_id_s == event_type_id) and (Counter(priorities_s) == Counter(priorities))):
                        success_subscription = update_subscription(subscription, pe_id, filter_id=row.pr_subscription.filter_id, subscription_id=row.pr_subscription.id, attachment=attachment)
                        break
                else:
                    success_subscription = update_subscription(subscription, pe_id, attachment=attachment)
            else:
                success_subscription = update_subscription(subscription, pe_id, attachment=attachment)
            if (('FTP' in subscription['method']) and formvars.repository_id):
                properties = self._update_sync(subscription['subscribe'][0]['resource'], subscription.get('filters'), int(formvars.repository_id), properties)
                properties = json.dumps(properties)
                query = (((base_query & (stable.pe_id == pe_id)) & (stable.owned_by_group == None)) & (stable.owned_by_user == user_id))
                db(query).update(comments=properties)
            else:
                self._remove_sync(properties)
                query = (((base_query & (stable.pe_id == pe_id)) & (stable.owned_by_group == None)) & (stable.owned_by_user == user_id))
                db(query).update(comments=None)
            redirect(URL(c='pr', f='subscription'))
        if success_subscription:
            response.confirmation = messages.SUCCESS
        else:
            response.error = messages.ERROR
    return form
