#!/usr/bin/env python

"""
metadata
~~~~~~~~~~~~~~~~~
Download metadata from the commandline
"""

import argparse
from datetime import datetime

from src.dhis.core import Dhis
from src.dhis.helpers import properties_to_remove


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

    def get_metadata(self, o_type, o_filter, file_type, fields=':all'):

        to_remove = ",!{}".format(",!".join(properties_to_remove))

        params = {
            'fields': '{}{}'.format(fields, to_remove),
            'filter': o_filter,
            'paging': False
        }
        response = self.get(endpoint=o_type, file_type=file_type, params=params)
        if file_type == 'json':
            return self.delete_properties_from_response(response)
        else:
            return response

    def delete_properties_from_response(self, resp, attr_rm=properties_to_remove):
        """ Remove all keys which are in the list (see param)"""
        for k in attr_rm:
            try:
                del resp[k]
            except KeyError:
                pass
        for v in resp.values():
            if isinstance(v, dict):
                self.delete_properties_from_response(v, attr_rm)
            elif isinstance(v, list):
                for elem in v:
                    self.delete_properties_from_response(elem, attr_rm)
        return resp


file_types = ['json', 'xml', 'csv']

parser = argparse.ArgumentParser(description="Download metadata")
parser.add_argument('-s', dest='server', action='store', help="Server, e.g. play.dhis2.org/demo", required=True)
parser.add_argument('-t', dest='object_type', action='store', required=True,
                    help="DHIS2 object type to get, e.g. -t=dataElements")
parser.add_argument('-f', dest='object_filter', action='store', help="Object filter, e.g. -f='name:like:Acute'",
                    required=False)
parser.add_argument('-e', dest='fields', action='store', help="Fields to include, e.g. -f='id,name'", default=':all', required=False)
parser.add_argument('-y', dest='file_type', action='store', help="File format, defaults to JSON", required=False, choices=file_types,
                    default='json')
parser.add_argument('-u', dest='username', action='store', help="DHIS2 username", required=True)
parser.add_argument('-p', dest='password', action='store', help="DHIS2 password", required=True)
parser.add_argument('-v', dest='api_version', action='store', required=False, type=int,
                    help='DHIS2 API version e.g. -v=24')
parser.add_argument('-d', dest='debug', action='store_true', default=False, required=False,
                    help="Debug flag - writes more info to log file")

args = parser.parse_args()

dhis = Downloader(server=args.server, username=args.username, password=args.password, api_version=args.api_version,
                  debug_flag=args.debug)
dhis.log.startinfo(__file__)

o_type = dhis.get_object_type(args.object_type)
data = dhis.get_metadata(o_type=o_type, o_filter=args.object_filter, file_type=args.file_type, fields=args.fields)

if not args.debug:
    print("To see the URL used, add '-d' to the script arguments and look in dhis2-pk.log")

# file name stuff
now = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
server_name = args.server.replace('https://', '').replace('.', '-').replace('/', '-')
if args.object_filter:
    file_name = "{}_{}_{}_FILTERED.{}".format(now, server_name, o_type, args.file_type)
else:
    file_name = "{}_{}_{}.{}".format(now, server_name, o_type, args.file_type)

# saving the file depending on format
if args.file_type == 'json':
    # https://stackoverflow.com/questions/12309269/how-do-i-write-json-data-to-a-file-in-python
    import json
    import codecs

    with open(file_name, 'wb') as json_file:
        json.dump(data, codecs.getwriter('utf-8')(json_file), ensure_ascii=False, indent=4)
else:
    with open(file_name, 'w') as other_file:
        other_file.write(str(data.encode('utf-8')))

dhis.log.info("{} file written to {}".format(args.file_type.upper(), file_name))
