import os
import unittest

from rdflib import Graph

from fhirtordf.fhir.fhirmetavoc import FHIRMetaVocEntry
from fhirtordf.loaders.fhirresourceloader import FHIRResource
from fhirtordf.rdfsupport.rdfcompare import rdf_compare
from tests.utils import SKIP_ALL_FHIR_ELEMENTS
from tests.utils.base_test_case import make_and_clear_directory, fhir_decimal_issue_filter
from tests.utils.build_test_harness import ValidationTestCase


class FHIRInstanceTestCase(ValidationTestCase):
    """ This test case is designed to traverse the FHIR publish directory, converting all reasonably sized
    JSON files into their RDF equivalent and then comparing the results to the '.ttl' generated by the FHIR
    build process.  If the files do not compare, a summary of the differences and the generated RDF is saved in
    the local data/all_fhir_elements_failures directory
    """
    @classmethod
    def setUpClass(cls):
        from tests.utils.base_test_case import FHIRGraph
        cls.fhir_ontology = FHIRGraph()

FHIRInstanceTestCase.no_tests = SKIP_ALL_FHIR_ELEMENTS            # Set this to True if you want to omit the batch tests
FHIRInstanceTestCase.single_file = SKIP_ALL_FHIR_ELEMENTS         # True makes life simpler

# To run this test, you need to check out an image of the STU3 build and point this directory at it
FHIRInstanceTestCase.input_directory = "/Users/mrf7578/Development/fhir/build/publish"
FHIRInstanceTestCase.output_directory = \
    os.path.join(os.path.split(os.path.abspath(__file__))[0], 'data', 'all_fhir_elements_failures')
FHIRInstanceTestCase.file_suffix = ".json"
FHIRInstanceTestCase.skip = ['valuesets.json', 'xds-example.json']
FHIRInstanceTestCase.file_filter = lambda dp, fn: ".cs." not in fn and '.vs.' not in fn and '.profile.' not in fn \
                                                  and '.canonical' not in fn and '/v2/' not in dp and '/v3/' not in dp \
                                                  and '.schema.' not in fn and '.diff.' not in fn
FHIRInstanceTestCase.base_dir = 'http://hl7.org/fhir'
FHIRInstanceTestCase.max_size = 20                 # maximum file size in kb
#FHIRInstanceTestCase.start_at = "bundle-example"


# Comparing to FHIR, so make certain we're doing FHIR dates
FHIRMetaVocEntry.fhir_dates = True


def json_to_ttl(self: FHIRInstanceTestCase, dirpath: str, fname: str) -> bool:
    json_file = os.path.join(dirpath, fname)
    turtle_fname = fname.rsplit('.', 1)[0] + '.ttl'
    source = FHIRResource(self.fhir_ontology, json_file, FHIRInstanceTestCase.base_dir)
    test_ttl_fname = os.path.join(dirpath, turtle_fname)
    if os.path.exists(test_ttl_fname):
        target = Graph()
        target.load(test_ttl_fname, format="turtle")
        diffs_nc = rdf_compare(target, source.graph, ignore_owl_version=True, ignore_type_arcs=True)
        diffs = rdf_compare(target, source.graph, ignore_owl_version=True, ignore_type_arcs=True,
                            compare_filter=fhir_decimal_issue_filter)
        if diffs_nc and not diffs:
            print("---> {} has decimal precision issues".format(fname))
        if diffs:
            with open(os.path.join(self.output_directory, turtle_fname), 'w') as f:
                f.write(diffs)
                f.write('\n\n' + '='*40 + '\n')
                f.write(str(source))
            return False
        return True
    else:
        print("===> {} does not exist!".format(test_ttl_fname))
        return True


FHIRInstanceTestCase.validation_function = json_to_ttl

if not FHIRInstanceTestCase.no_tests and not FHIRInstanceTestCase.single_file:
    make_and_clear_directory(FHIRInstanceTestCase.output_directory)
FHIRInstanceTestCase.build_test_harness()


if __name__ == '__main__':
    unittest.main()
