#!/usr/bin/env python

"""
share-objects
~~~~~~~~~~~~~~~~~
This script assigns sharing to shareable DHIS2 objects like userGroups and publicAccess.
"""

import argparse
import sys

from core.core import Dhis


class Sharer(Dhis):
    """Inherited from core Dhis class to extend functionalities"""

    def __init__(self, server, username, password, debug_flag):
        Dhis.__init__(self, server, username, password, debug_flag)

    def get_usergroup_uid(self, usergroup_name):
        """Get UID of userGroup based on userGroup.name"""

        params = {
            'fields': 'id,name',
            'paging': False,
            'filter': 'name:like:' + usergroup_name
        }

        print("Getting {} UID...".format(usergroup_name))

        endpoint = 'userGroups'
        response = self.get(endpoint=endpoint, params=params)

        if len(response['userGroups']) == 1:
            uid = response['userGroups'][0]['id']
            self.log.info("{} UID: {}".format(usergroup_name, uid))
            return uid
        else:
            self.log.info("Failure in getting (only one) userGroup UID for filter 'name:like:{}'".format(usergroup_name))
            sys.exit()

    def get_objects(self, objects, objects_filter):
        """Returns filtered DHIS2 objects"""

        params = {
            'fields': 'id,name,code',
            'filter': objects_filter,
            'paging': False
        }
        print("Getting {} with filter {}".format(objects, objects_filter))
        response = self.get(endpoint=objects, params=params)

        if len(response[objects]) > 0:
            return response
        else:
            self.log.info('No objects found. Wrong filter?')
            sys.exit()

    def share_object(self, payload, parameters):
        """Share object by using sharing enpoint"""
        self.post(endpoint="sharing", params=parameters, payload=payload)


# argument parsing
parser = argparse.ArgumentParser(description="Share DHIS2 objects (dataElements, programs, ...) with userGroups")
parser.add_argument('-s', '--server', action='store', required=True,
                    help="DHIS2 server, e.g. 'play.dhis2.org/demo'")
parser.add_argument('-t', '--object_type', action='store', required=True, choices=Dhis.objects_types,
                    help="DHIS2 objects to apply sharing")
parser.add_argument('-f', '--filter', action='store', required=True,
                    help="Filter on object name according to DHIS2 field filter")
parser.add_argument('-w', '--usergroup_readwrite', action='store', required=False,
                    help="UserGroup Name with Read-Write rights")
parser.add_argument('-r', '--usergroup_readonly', action='store', required=False,
                    help="UserGroup Name with Read-Only rights")
parser.add_argument('-a', '--publicaccess', action='store', required=True, choices=Dhis.public_access.keys(),
                    help="publicAccess (with login)")
parser.add_argument('-u', '--username', action='store', required=True, help='DHIS2 username')
parser.add_argument('-p', '--password', action='store', required=True, help='DHIS2 password')
parser.add_argument('-d', '--debug', action='store_true', default=False, required=False, help="Writes more info in log file")
args = parser.parse_args()

# init DHIS
dhis = Sharer(server=args.server, username=args.username, password=args.password, debug_flag=args.debug)

# get UID of usergroup with RW access
readwrite_usergroup_uid = dhis.get_usergroup_uid(args.usergroup_readwrite)

# get UID of usergroup with RO access
readonly_usergroup_uid = dhis.get_usergroup_uid(args.usergroup_readonly)

# split arguments for multiple filters
filter_list = args.filter.split('&')

# pull objects for which to apply sharing
data = dhis.get_objects(args.object_type, filter_list)

no_of_obj = len(data[args.object_type])

dhis.log.info("Fetched {} {} to apply sharing...".format(str(no_of_obj), args.object_type))

counter = 1
for obj in data[args.object_type]:
    payload = {
        'meta': {
            'allowPublicAccess': True,
            'allowExternalAccess': False
        },
        'object': {
            'id': obj['id'],
            'name': obj['name'],
            'publicAccess': Dhis.public_access[args.publicaccess],
            'externalAccess': False,
            'user': {},
            'userGroupAccesses': [
                {
                    'id': readwrite_usergroup_uid,
                    'access': Dhis.public_access['readwrite']
                },
                {
                    'id': readonly_usergroup_uid,
                    'access': Dhis.public_access['readonly']
                }
            ]
        }
    }
    # strip name to match API (e.g. dataElements -> dataElement)
    parameters = {
        'type': args.object_type[:-1],
        'preheatCache': False,
        'id': obj['id']
    }

    # apply sharing
    dhis.share_object(payload, parameters)

    dhis.log.info("({}/{}) [OK] {}".format(str(counter), str(no_of_obj), obj['name']))
    counter += 1
