# AUTOGENERATED! DO NOT EDIT! File to edit: 00_core.ipynb (unless otherwise specified).

__all__ = ['request_headers', 'get_as_raw_json', 'get_next_as_raw_json', 'timestamp_now', 'new_bundle', 'new_list',
           'extract_references_from_resource', 'extract_references', 'get_by_reference', 'filter_bundle']

# Cell
import requests
from datetime import datetime, timezone
from uuid import uuid4

# Cell
# TODO: fix this hack
request_headers = {}

# Cell
def get_as_raw_json(api_base, resource_type, id_or_params=None):
    "GET FHIR resources of `resource_type` in JSON format"
    url = f'{api_base}/{resource_type}'
    params = dict(_format = 'json')
    if isinstance(id_or_params, dict): params = {**params, **id_or_params}
    elif isinstance(id_or_params, str):
        if id_or_params[0] in ['/','?']: raise Exception(f'invalid id_or_params {id_or_params}') # TODO: clean
        url += f'/{id_or_params}'
    response = requests.get(url, params, headers=request_headers)
    print('GET', response.url)
    return response.json()

# Cell
def get_next_as_raw_json(json_response):
    "GET the next set of results"
    for link in json_response['link']:
        if link['relation'] == 'next':
            url = link['url']
            print('GET',url)
            return requests.get(url, headers=request_headers).json()

# Cell
def timestamp_now():
    return datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')

# Cell
def new_bundle(bundle_type='collection'):
    return dict(resourceType='Bundle',
                id=str(uuid4()),
                type=bundle_type,
                timestamp=timestamp_now(),
                entry=[])

# Cell
def new_list(title, status='current', mode='snapshot'):
    return dict(resourceType='List',
                id=str(uuid4()),
                title=title,
                status=status,
                mode=mode,
                date=timestamp_now(),
                entry=[])

# Cell
def extract_references_from_resource(resource, field_name):
    "Return a list of references extracted from a single resource and field"
    result = []
    if field_name in resource:
        references = resource[field_name]
        if not isinstance(references, list): references = [references]
        for reference in references:
            _reference = reference.get('reference')
            if _reference is None: continue
            if _reference.startswith('#'): continue
            # TODO: check that we have a relative reference or handle other kinds too
            result.append(_reference)
    return result

# Cell
def extract_references(bundle, field_names):
    "Return a list of relative references e.g. `['Condition/1ddef4ad-fb76-46d6-9f1d-8ed58b173ee8']`"
    if 'entry' not in bundle: return []
    result = []
    for entry in bundle['entry']:
        resource = entry.get('resource', {})
        for f in field_names:
            result.extend(extract_references_from_resource(resource, f))
    return list(set(result)) # de-duplicate but still return a list

# Cell
def get_by_reference(api_base, reference):
    "Return a resource read from a FHIR server by reference, as a list containg a single bundle entry"
    if reference.startswith(api_base):
        reference = reference[len(api_base):].strip('/')
    if reference.startswith('http'):
        print(f'WARNING: Found reference {reference} that does not start with {api_base}')
        return []
    resource_type, id = reference.split('/')
    single_resource = get_as_raw_json(api_base, resource_type, id)
    return [dict(fullUrl = f'{api_base}/{resource_type}/{id}', resource = single_resource)]

# Cell
def filter_bundle(bundle, filter_fn):
    "Apply a filter function to a bundle in-place"
    bundle['entry'] = [e for e in bundle['entry'] if filter_fn(e)]
    return bundle