import json


def update_permissions_for_annotation(
        gc, annotation_id=None, annotation=None,
        groups_to_add=None, replace_original_groups=True,
        users_to_add=None, replace_original_users=True):
    """Update permissions for a single annotation.

    Parameters
    ----------
    gc : gider_client.GirderClient
        authenticated girder client instance
    annotation_id : str
        girder id of annotation
    annotation : dict
        overrides annotation_id if given
    groups_to_add : list
        each entry is a dict containing the information about user groups
        to add and their permission levels. A sample entry must have the
        following keys
        - level, int -> 0 (view), 1 (edit) or 2 (owner)
        - name, str -> name of user group
        - id, st -> girder id of user group
    replace_original_groups : bool
        whether to replace original groups or append to them
    users_to_add : list
        each entry is a dict containing the information about user
        to add and their permission levels. A sample entry must have the
        following keys
        - level, int -> 0 (view), 1 (edit) or 2 (owner)
        - login, str -> username of user
        - id, st -> girder id of user
    replace_original_users
        whether to replace original users or append to them

    Returns
    -------
    dict
        server response

    """
    groups_to_add = [] if groups_to_add is None else groups_to_add
    users_to_add = [] if users_to_add is None else users_to_add

    if annotation is not None:
        annotation_id = annotation['_id']
    elif annotation_id is None:
        raise Exception(
            "You must provide either the annotation or its girder id.")

    # get current permissions
    current = gc.get('/annotation/%s/access' % annotation_id)

    # add or replace as needed
    if replace_original_groups:
        current['groups'] = []
        current_group_ids = []
    else:
        current_group_ids = [j['id'] for j in current['groups']]

    if replace_original_users:
        current['users'] = []
        current_user_ids = []
    else:
        current_user_ids = [j['id'] for j in current['users']]

    for group in groups_to_add:
        if group['id'] not in current_group_ids:
            current['groups'].append(group)

    for user in users_to_add:
        if user['id'] not in current_user_ids:
            current['users'].append(user)

    # now update accordingly
    # BAD WAY!! -- do NOT do this!
    # return gc.put('/annotation/%s/access?access=%s' % (
    #        annotation_id, json.dumps(current)))
    # PROPER WAY
    return gc.put('/annotation/%s/access' % annotation_id, data={
        'access': json.dumps(current)})