import argparse
import json
import sys
import time

import requests

try:
    from core.config import DhisConfig
    from core.dhis import Dhis
    from core.helpers import Color
    from core.exceptions.__init__ import db_exceptions
    from core.exceptions.warnings import ValidationWarning
    from core.exceptions.errors import ValidationError, ImportException
except ImportError:
    from smartvadhis2.core.config import DhisConfig
    from smartvadhis2.core.dhis import Dhis
    from smartvadhis2.core.helpers import Color
    from smartvadhis2.core.exceptions.__init__ import db_exceptions
    from smartvadhis2.core.exceptions.warnings import ValidationWarning
    from smartvadhis2.core.exceptions.errors import ValidationError, ImportException

"""
Module to provide various ad-hoc commands not to be run regularly
"""


def parse_args():
    parser = argparse.ArgumentParser(usage='%(prog)s', description="CLI helpers for smartvadhis2")

    group = parser.add_mutually_exclusive_group()

    group.add_argument('--delete_events',
                       dest='delete_events',
                       action='store_true',
                       required=False,
                       help="Delete all events"
                       )

    group.add_argument('--download_program_metadata',
                       dest='program_metadata',
                       action='store_true',
                       required=False,
                       help="Download DHIS2 program metadata"
                       )

    group.add_argument('--print_error_categories',
                       dest='error_categories',
                       action='store_true',
                       required=False,
                       help="Print error categories inserted into the database"
                       )

    arguments = parser.parse_args()
    if not any([arguments.delete_events, arguments.program_metadata, arguments.error_categories]):
        parser.error('Must provide an argument. see --help')
    return arguments


def remove_keys(obj, rubbish):
    """Recursively remove keys whose are in `rubbish` and return cleaned object"""
    if isinstance(obj, dict):
        obj = {
            key: remove_keys(value, rubbish)
            for key, value in obj.items()
            if key not in rubbish}
    elif isinstance(obj, list):
        obj = [remove_keys(item, rubbish)
               for item in obj
               if item not in rubbish]
    return obj


def delete_events():
    """Delete ALL Verbal Autopsy Program Events from DHIS2"""
    confirm = input('You are about to {}delete{} ALL Verbal Autopsy DHIS2 Program Events from {}{}. '
                    'Are you really sure? Type yes / no\n'.format(Color.RED, Color.BOLD, DhisConfig.baseurl, Color.END))
    if confirm.lower() == 'yes':
        api = Dhis()

        program_name = api.get(endpoint='programs/{}'.format(DhisConfig.program_uid)).json().get('name')

        params = {
            'program': DhisConfig.program_uid,
            'skipPaging': True,
            'fields': 'event'
        }
        events = api.get(endpoint='events', params=params).json()

        no_of_events = len(events['events'])
        print("Deleting {}{} events{} for the '{}' program ({})...".format(Color.BOLD, no_of_events, Color.END,
                                                                           program_name, DhisConfig.program_uid))
        time.sleep(5)
        for i, event in enumerate(events['events'], 1):
            r = api.delete('events/{}'.format(event['event']))
            try:
                r.raise_for_status()
            except requests.HTTPError:
                print(r.text)
            else:
                print("[{}/{}] Deleted {}".format(i, no_of_events, event['event']))
    else:
        print("Aborted.")
        sys.exit(0)


def download_program_metadata(skip_csv_metadata=True):
    """
    Download metadata from server and clean up some properties that might create problems in another DHIS2 instance
    If skip_csv_metadata is false, additional properties are returned that are already provided
    in the metadata folder
    """
    api = Dhis()

    metadata = api.get(endpoint='programs/{}/metadata.json'.format(DhisConfig.program_uid)).json()

    if skip_csv_metadata:
        remove_obj = ['dataElements', 'optionSets', 'options']
        descriptor = 'partial (no {}) program metadata'.format('/'.join(remove_obj))
        for obj in remove_obj:
            metadata.pop(obj, None)
    else:
        descriptor = 'full program metadata'

    metadata.pop('categoryCombos', None)
    metadata.pop('categoryOptions', None)
    metadata.pop('categoryOptionCombos', None)
    metadata.pop('categories', None)
    metadata['programs'][0]['version'] = 0
    metadata['programs'][0]['organisationUnits'] = []
    metadata = remove_keys(metadata, ['lastUpdatedBy', 'user'])

    filename = 'program_metadata.json'
    with open(filename, 'w') as f:
        json.dump(metadata, f, sort_keys=True, indent=4)
    print("Exported {} to {}{}{}".format(descriptor, Color.BOLD, filename, Color.END))


def print_error_categories():
    """
    Print exception categories that are inserted into the local database
    """

    def print_tuple(data, msg):
        """Sort by code and print"""
        print(msg)
        [print('- ID:{} - {}'.format(tup[0], tup[1])) for tup in sorted(data, key=lambda tup: tup[0])]

    val_err = [(e.code, e.message) for e in db_exceptions if e.code in range(600, 700)]
    print_tuple(val_err, 'Validation Errors (600-699)')

    import_err = [(e.code, e.message) for e in db_exceptions if e.code in range(700, 800)]
    print_tuple(import_err, 'Import Errors (700-799)')

    var_warn = [(w.code, w.message) for w in db_exceptions if w.code in range(800, 900)]
    print_tuple(var_warn, 'Validation Warnings (800-899)')


def main():
    args = parse_args()
    if args.delete_events:
        delete_events()
    if args.program_metadata:
        download_program_metadata()
    if args.error_categories:
        print_error_categories()


if __name__ == '__main__':
    main()

import argparse
import json
import sys
import time

import requests

try:
    from core.config import DhisConfig
    from core.dhis import Dhis
    from core.helpers import Color
    from core.exceptions.__init__ import db_exceptions
    from core.exceptions.warnings import ValidationWarning
    from core.exceptions.errors import ValidationError, ImportException
except ImportError:
    from smartvadhis2.core.config import DhisConfig
    from smartvadhis2.core.dhis import Dhis
    from smartvadhis2.core.helpers import Color
    from smartvadhis2.core.exceptions.__init__ import db_exceptions
    from smartvadhis2.core.exceptions.warnings import ValidationWarning
    from smartvadhis2.core.exceptions.errors import ValidationError, ImportException

"""
Module to provide various ad-hoc commands not to be run regularly
"""


def parse_args():
    parser = argparse.ArgumentParser(usage='%(prog)s', description="CLI helpers for smartvadhis2")

    group = parser.add_mutually_exclusive_group()

    group.add_argument('--delete_events',
                       dest='delete_events',
                       action='store_true',
                       required=False,
                       help="Delete all events"
                       )

    group.add_argument('--download_program_metadata',
                       dest='program_metadata',
                       action='store_true',
                       required=False,
                       help="Download DHIS2 program metadata"
                       )

    group.add_argument('--print_error_categories',
                       dest='error_categories',
                       action='store_true',
                       required=False,
                       help="Print error categories inserted into the database"
                       )

    arguments = parser.parse_args()
    if not any([arguments.delete_events, arguments.program_metadata, arguments.error_categories]):
        parser.error('Must provide an argument. see --help')
    return arguments


def remove_keys(obj, rubbish):
    """Recursively remove keys whose are in `rubbish` and return cleaned object"""
    if isinstance(obj, dict):
        obj = {
            key: remove_keys(value, rubbish)
            for key, value in obj.items()
            if key not in rubbish}
    elif isinstance(obj, list):
        obj = [remove_keys(item, rubbish)
               for item in obj
               if item not in rubbish]
    return obj


def delete_events():
    """Delete ALL Verbal Autopsy Program Events from DHIS2"""
    confirm = input('You are about to {}delete{} ALL Verbal Autopsy DHIS2 Program Events from {}{}. '
                    'Are you really sure? Type yes / no\n'.format(Color.RED, Color.BOLD, DhisConfig.baseurl, Color.END))
    if confirm.lower() == 'yes':
        api = Dhis()

        program_name = api.get(endpoint='programs/{}'.format(DhisConfig.program_uid)).json().get('name')

        params = {
            'program': DhisConfig.program_uid,
            'skipPaging': True,
            'fields': 'event'
        }
        events = api.get(endpoint='events', params=params).json()

        no_of_events = len(events['events'])
        print("Deleting {}{} events{} for the '{}' program ({})...".format(Color.BOLD, no_of_events, Color.END,
                                                                           program_name, DhisConfig.program_uid))
        time.sleep(5)
        for i, event in enumerate(events['events'], 1):
            r = api.delete('events/{}'.format(event['event']))
            try:
                r.raise_for_status()
            except requests.HTTPError:
                print(r.text)
            else:
                print("[{}/{}] Deleted {}".format(i, no_of_events, event['event']))
    else:
        print("Aborted.")
        sys.exit(0)


def download_program_metadata(skip_csv_metadata=True):
    """
    Download metadata from server and clean up some properties that might create problems in another DHIS2 instance
    If skip_csv_metadata is false, additional properties are returned that are already provided
    in the metadata folder
    """
    api = Dhis()

    metadata = api.get(endpoint='programs/{}/metadata.json'.format(DhisConfig.program_uid)).json()

    if skip_csv_metadata:
        remove_obj = ['dataElements', 'optionSets', 'options']
        descriptor = 'partial (no {}) program metadata'.format('/'.join(remove_obj))
        for obj in remove_obj:
            metadata.pop(obj, None)
    else:
        descriptor = 'full program metadata'

    metadata.pop('categoryCombos', None)
    metadata.pop('categoryOptions', None)
    metadata.pop('categoryOptionCombos', None)
    metadata.pop('categories', None)
    metadata['programs'][0]['version'] = 0
    metadata['programs'][0]['organisationUnits'] = []
    metadata = remove_keys(metadata, ['lastUpdatedBy', 'user'])

    filename = 'program_metadata.json'
    with open(filename, 'w') as f:
        json.dump(metadata, f, sort_keys=True, indent=4)
    print("Exported {} to {}{}{}".format(descriptor, Color.BOLD, filename, Color.END))


def print_error_categories():
    """
    Print exception categories that are inserted into the local database
    """

    def print_tuple(data, msg):
        """Sort by code and print"""
        print(msg)
        [print('- ID:{} - {}'.format(tup[0], tup[1])) for tup in sorted(data, key=lambda tup: tup[0])]

    val_err = [(e.code, e.message) for e in db_exceptions if e.code in range(600, 700)]
    print_tuple(val_err, 'Validation Errors (600-699)')

    import_err = [(e.code, e.message) for e in db_exceptions if e.code in range(700, 800)]
    print_tuple(import_err, 'Import Errors (700-799)')

    var_warn = [(w.code, w.message) for w in db_exceptions if w.code in range(800, 900)]
    print_tuple(var_warn, 'Validation Warnings (800-899)')


def main():
    args = parse_args()
    if args.delete_events:
        delete_events()
    if args.program_metadata:
        download_program_metadata()
    if args.error_categories:
        print_error_categories()


if __name__ == '__main__':
    main()

Module to provide various ad-hoc commands not to be run regularly Recursively remove keys whose are in `rubbish` and return cleaned object Delete ALL Verbal Autopsy Program Events from DHIS2 Download metadata from server and clean up some properties that might create problems in another DHIS2 instance     If skip_csv_metadata is false, additional properties are returned that are already provided     in the metadata folder Print exception categories that are inserted into the local database Sort by code and print