class Patient(HubEntity):
    """Patienten zijn alle personen in de rol van patient.
    bk: registratie_syteem + inschrijvingsnummer"""

    # hub = Hub('patient')
    class Inschrijving(Sat):
        bsn = Columns.TextColumn()
        inschrijfnummer = Columns.TextColumn()
        inschrijfdatum = Columns.DateTimeColumn()

    class Default(Sat):
        geboortedatum = Columns.DateColumn()

    class Personalia(Sat):
        achternaam = Columns.TextColumn()
        tussenvoegsels = Columns.TextColumn()
        voorletters = Columns.TextColumn()
        voornaam = Columns.TextColumn()

    class Adres(Sat):
        postcode = Columns.TextColumn()
        huisnummer = Columns.IntColumn()
        huisnummer_toevoeging = Columns.TextColumn()
        straat = Columns.TextColumn()
        plaats = Columns.TextColumn()
        land = Columns.TextColumn()

    class Contactgegevens(HybridSat):
        class Types(HybridSat.Types):
            telefoon = 'telefoon'
            mobiel = 'mobiel'
            mobiel2 = 'mobiel2'
        telnummer = Columns.TextColumn()
        datum = Columns.DateColumn()
    #
    # default = Default()
    # personalia = Personalia()
    # adres = Adres()
    # inschrijving = Inschrijving()
    # contactgegevens = ContactGegevens() class Traject(HubEntity):
    class Default(Sat):
        naam = Columns.TextColumn()
        start = Columns.DateTimeColumn()
        eind = Columns.DateTimeColumn('sluit_datum')
        nummer = Columns.IntColumn()
        status =  Columns.TextColumn()

    class RecordStatus(RecordStatusSat):
        pass class Patient_Traject_Link(LinkEntity):
    class Link(Link):
        patient = LinkReference(Patient)
        traject = LinkReference(Traject)

    class Default(Sat):
        start = Columns.DateTimeColumn()
        eind = Columns.DateTimeColumn('sluit_datum')
        status = Columns.TextColumn()

    class RecordStatus(RecordStatusSat):
        pass class SubTraject(Traject):
    class SubTraject(Sat):
        declaratie_nummer = Columns.IntColumn() class Handeling(HubEntity):
    class Default(Sat):
        naam = Columns.TextColumn()
        dbc_activiteit_code = Columns.TextColumn()
        datum = Columns.DateTimeColumn() class Zorginstelling(Organisatie):
    class Zorginstelling(Sat):
        agbnummer = Columns.TextColumn() class Zorgverzekeraar(Organisatie):
    class Zorgverzekeraar(Sat):
        nummer = Columns.TextColumn() class Locatie(HubEntity):
    class Default(Sat):
        naam = Columns.TextColumn()
        kamernummer = Columns.TextColumn()
        lat_long = Columns.TextColumn() class Hulpverlener(HubEntity):
    class Default(Sat):
        naam = Columns.TextColumn()
        agbnummer = Columns.TextColumn() class PatientHandelingLink(LinkEntity):
    class Link(HybridLink):
        class Types():
            hulpverlener = Hulpverlener
            zorginstelling = Zorginstelling
            zorgverzekeraar = Zorgverzekeraar
            locatie = Locatie

        Patient = LinkReference(Patient)
        Handeling = LinkReference(Handeling)
        Dynamic = DynamicLinkReference() def get_root_path():
    """

    :rtype : object
    """
    import os
    path = os.path.dirname(__file__)
    path = path.replace('\\', '/')
    path = path[0: path.rfind('/')]
    return path class MappingWriter():
    @staticmethod
    def create_python_code_mappings(sor_table: 'Table', entity: HubEntity) -> None:
        """helper functie om mappings aan te maken in string format"""
        if len(sor_table.columns) == 0: sor_table.reflect()
        s = """def init_sor_{}_to_{}_mappings(sor):\r\n""".format(sor_table.name, entity.__name__.lower())
        s += """    mappings = []\r\n"""
        s += """\r\n    # ###########################\r\n"""
        s += """    # Beschikbare velden {}:\r\n""".format(sor_table.name.upper())
        s += '    # '
        idx = 0
        for col in sor_table.columns:
            source = col.name.lower()
            if source.startswith('_'): continue
            s += """{}, """.format(source)
            idx += 1
            if idx == 10:
                idx = 0
                s += '\r\n'
                s += '    # '
        s += """\r\n\r\n"""
        s += """    mapping = SorToEntityMapping('{0}', {1}, sor)\r\n""".format(sor_table, entity.__name__)
        s += """    mapping.map_bk([''])\r\n""".format(sor_table, entity.__name__)
        for sat_name, sat in entity.cls_get_sats().items():
            # sat.cls_init_cols()
            s += """\r\n""".format(sor_table, entity.__name__)
            s += """    #SAT {}.{}\r\n""".format(entity.__name__, sat_name)
            for col in sat.cls_get_columns():
                if col.name.startswith('_'):
                    continue
                source = ''
                if col.type != 'text':
                    # cast
                    source = "::{1}""".format(source, col.type)

                if sat.__base__ == HybridSat:
                    first_type = ''
                    if 'Types' in sat.__dict__:
                        for k, name in sat.Types.__dict__.items():
                            if not k.startswith('__'):
                                first_type = k
                                break
                    s += """    mapping.map_field("{0}", {1}.{2}.{3}, type={1}.{2}.Types.{4})\r\n""".format(source, entity.__name__, sat_name, col.name, first_type)
                else:
                    s += """    mapping.map_field("{0}", {1}.{2}.{3})\r\n""".format(source, entity.__name__, sat_name, col.name)

        s += """    mappings.append(mapping)\r\n"""
        s += """    return mappings\r\n"""
        s += """\r\n"""
        print(s)
        return s

    @staticmethod
    def create_python_code_dm_mappings(source_schema, source_name: str, dm_schema, dim: Dim) -> None:
        col_names = ''
        if source_name:
            inspector = reflection.Inspector.from_engine(dm_schema.db.engine)
            cols = inspector.get_columns(source_name, source_schema)
            i = 0
            for col in cols:
                col_names += col['name'] + ', '
                if i> 0 and i % 5 == 0:
                    col_names += '\r\n    # '
                i += 1

        """helper functie om mappings aan te maken in string format"""
        s = """def init_{}_{}_to_{}_mappings():\r\n""".format(source_schema, source_name, dim.cls_get_name())
        s += """\r\n    # ###########################\r\n"""
        s += """    # Beschikbare velden: {}\r\n""".format(col_names)
        s += '    \r\n'
        s += '    source_sql = "SELECT * FROM {}.{}"\r\n'.format(source_schema, source_name)
        s += '    mapping = DvToDimMapping(source_sql, {})\r\n'.format(dim.__name__)
        for col in dim.__cols__:
            s += """    mapping.map_field('', {}.{})\r\n""".format(dim.__name__, col.name)
        s += """    return mapping\r\n"""
        s += """\r\n"""
        print(s)
        return s

    @staticmethod
    def create_python_code_mappings_old(table: 'Table', remove_prefix: str = '') -> None:
        """helper functie om mappings aan te maken in string format"""
        if len(table.columns) == 0: table.reflect()
        s = """mapping = SorToEntityMapping('{0}_hstage', {0}_entity)\r\n""".format(table.name)
        for col in table.columns:
            source = col.name.lower()
            target = col.name.lower().replace(remove_prefix, '')
            type = MappingWriter.oracle_type_to_postgres_type(col.type)
            if type != 'text':
                #cast
                source = "{0}::{1}""".format(source, type)
            s += """mapping.map_field("{}", sat_prop)\r\n""".format(source)
        print(s)

    @staticmethod
    def oracle_type_to_postgres_type(type: str) -> str:
        type = type.lower().strip()
        if 'string' in type:
            return 'text'
        elif 'varchar' in type:
            return 'text'
        elif 'number' in type:
            return 'numeric'
            #todo integers
        elif 'datetime' in type:
            return 'timestamp'
        else:
            return type class ConstantValue:
    def __init__(self, value, type: str = 'text', alias: str = '') -> None:
        self.value = value
        self.type = type

    def __str__(self) -> str:
        if isinstance(self.value, str) and self.type == 'text':
            if "'" in self.value:
                return "{}".format(self.value)
            else:
                return "'{}'".format(self.value)
        else:
            return "{}".format(self.value) class SorToEntityMapping(BaseTableMapping):
    def __init__(self, source: str, target: HubEntity, sor: Schema = None, filter: str = '', type: str = '') -> None:
        # target.cls_init_sats()

        # if not sor:
        #     sor_name = source.split('.')[0]
        #     from pyelt.pipeline import Pipeline
        #     p = Pipeline()
        #     db = p.dwh
        #     sor = db.get_sor_schema(sor_name)
        if isinstance(source, str) and 'SELECT' in source.upper() and ' ' in source:
            source = SorQuery(source, sor)
        elif isinstance(source, str):
            source = SorTable(source, sor)
        if not sor and source is SorTable:
            raise Exception('Je moet een sor laag opgeven bij aanmaken van de SorToEntityMapping')
        # target.init_cls()
        super().__init__(source, target, filter)
        self.entity = target
        self.type = type
        if not type and not target.__base__ == HubEntity:
            self.type = target.__subtype__
        self.sat_mappings = {} #type: Dict[str, SorSatMapping]
        self.bk_mapping = None #type: str
        self.key_mappings = []  # type: str

    def map_field(self, source: Union[str, 'ConstantValue', list, dict], target: 'Column' = None, transform_func: 'FieldTransformation'=None, ref: str = '', type: str = '') -> None:
        if not source:
            return
        if not target:
            return
        if target.name == 'bk':
            return self.map_bk(source)
        sat = target.get_table()

        sat_name = sat.cls_get_name()
        sat_mapping = SorSatMapping(self.source, sat, type)
        if not sat_mapping.name in self.sat_mappings:
            self.sat_mappings[sat_mapping.name] = sat_mapping
        else:
            sat_mapping = self.sat_mappings[sat_mapping.name]
        sat_mapping.map_field(source, target, transform_func, ref)
        sat_mapping.type = type
        # field_mapping = FieldMapping(source, target, transform_func, ref = ref)
        # self.field_mappings.append(field_mapping)

    def map_bk(self, source: Union[str,List[str]]) -> None:
        if isinstance(source, list):
            source = " || '.' ||".join(source)
        self.bk_mapping = source

    def map_keys_in_sat(self, source: Union[str, List[str]], target: Union['Column', List['Column']]):
        """In plaats van een bk_mapping kun je ook mappen op een veld combinatie in een reeds bestaande sat.

        Voorwaarde is dat er reeds een gevulde hub met een sat is, die vanuit een andere bron is gevuld.

        Denk hierbij ook aan een zogenaamde keys_sat: een sat met alleen sleutel info vanuit de verschillende bronnen"""
        if isinstance(source, list):
            for index in range(len(source)):
                self.key_mappings.append(KeyMapping(source[index], target[index]))



    def map_fixed_value(self, fixed_value: str, target_field: 'Column' = None) -> None:
        source_field = ConstantValue("'{}'".format(fixed_value))
        self.map_field(source_field, target_field) class SorToLinkMapping(BaseTableMapping):
    auto_generated_sor_fk = 'auto'

    def __init__(self, source: Union[str, 'Table', 'View'], target: 'LinkEntity', sor: Schema, filter: str = '', type: str = '') -> None:
        if isinstance(source, str):
            source = SorTable(source, sor)
        super().__init__(source, target, filter)
        self.sor_table_name = str(source)
        if isinstance(type, str):
            self.type = type
        elif type == HubEntity:
            self.type = type.__subtype__
        self.target = target
        # self.target.cls_init()
        self.hubs = {} #type: Dict[str, Table]
        self.sat_mappings = {}  # type: Dict[str, Sat]

    def get_fk_name(self, entity_cls):
        for prop_name, entity in self.target.__dict__.items():
            if entity == entity_cls or entity == entity_cls.__base__:
                fk = """fk_{}""".format(entity.cls_get_hub_name())
                if prop_name.lower() != entity.__name__.lower():
                    fk = """fk_{}_{}""".format(prop_name.lower(), entity.cls_get_hub_name())
                return fk
        raise Exception('Entity niet gevonden in Link')

    def map_bk(self, source_bk, target_link_ref: Union[LinkReference, DynamicLinkReference], join: str = '', type: Union[str, 'HubEntity'] = ''):
        if not (isinstance(target_link_ref, LinkReference) or isinstance(target_link_ref, DynamicLinkReference)):
            raise PyeltException('Link moet verwijzen naar veld van type LinkReference of DynamicLinkReference')

        if isinstance(target_link_ref, LinkReference):
            hub_name = target_link_ref.hub.__dbname__
            hub = target_link_ref.hub

        elif isinstance(target_link_ref, DynamicLinkReference):
            # type verwijst hier naar de entity die dynamisch gelinkt wordt in de fk
            if not type or isinstance(type, str):
                raise PyeltException('Bij DynamicLinkReference moet type verwijzen naar een afgeleide van HubEntity')
            hub_name = type.cls_get_hub_name()
            hub = type.cls_get_hub()

            self.type = type.__name__.lower()
        hub_alias = target_link_ref.fk.replace('fk_', '')

        source_field = '_id' #type: str
        source_col = Column(source_field, 'integer', tbl=hub) #type: Column
        target_fk = target_link_ref.fk
        target_col = Column(target_fk, 'integer', tbl=hub)
        field_mapping = LinkFieldMapping(source_col, target_col)
        field_mapping.join = join
        field_mapping.source_alias = hub_alias
        if isinstance(source_bk, list):
            source_bk = "|| '.' || ".join(source_bk)
        field_mapping.bk = source_bk
        self.hubs[target_fk] = hub
        self.field_mappings.append(field_mapping)

    def map_sor_fk(self, source_fk: str = '', target_link_ref: Union[LinkReference, DynamicLinkReference] = None, join: str = '', type: Union[str, 'HubEntity'] = ''):
        if not (isinstance(target_link_ref, LinkReference) or isinstance(target_link_ref, DynamicLinkReference)):
            raise PyeltException('Link moet verwijzen naar veld van type LinkReference of DynamicLinkReference')
        if isinstance(target_link_ref, LinkReference):
            hub_name = target_link_ref.hub.__dbname__
            hub = target_link_ref.hub
            # if not type and target_link_ref.sub_entity_type != hub_name.replace('_hub', ''):
            #     type = target_link_ref.sub_entity_type
            # if not type and not target_link_ref.hub.__base__ == HubEntity:
            #     type = target_link_ref.hub.__dbname__.replace('_hub', '')

            if not source_fk or source_fk == SorToLinkMapping.auto_generated_sor_fk:
                # source_fk = target_link_ref.fk
                source_fk = 'fk_{}{}'.format(target_link_ref.sub_entity_type, hub_name)
        elif isinstance(target_link_ref, DynamicLinkReference):
            # type verwijst hier naar de entity die dynamisch gelinkt wordt in de fk
            if not type or isinstance(type, str):
                raise PyeltException('Bij DynamicLinkReference moet type verwijzen naar een afgeleide van HubEntity')
            hub = type.cls_get_hub()
            self.type = type.__name__.lower()
        source_col = Column(source_fk, 'integer', tbl=self.sor_table_name)

        target_fk = target_link_ref.fk
        target_col = Column(target_fk, 'integer', tbl=hub)
        field_mapping = LinkFieldMapping(source_col, target_col)
        field_mapping.join = join
        self.hubs[target_fk] = hub
        self.field_mappings.append(field_mapping)

    def map_entity(self, target_link_ref: Union[LinkReference, DynamicLinkReference] = None, bk: Union[List[str], str] = '', join: str = '', type: Union[str, 'HubEntity'] = ''):
        if isinstance(target_link_ref, DynamicLinkReference) and not bk:
            hub_name = type.cls_get_hub_name()
            sor_fk = 'fk_{}'.format(hub_name)
            self.map_sor_fk(sor_fk, target_link_ref, join, type)
        elif bk:
            self.map_bk(bk, target_link_ref, join, type)
        else:
            self.map_sor_fk('', target_link_ref, join, type)

    # def map_dynamic_entity(self, source_entity: HubEntity, target_link_ref: DynamicLinkReference,  type: str = '', bk: str = '', join: str = ''):
    #     if bk:
    #         self.map_bk(bk, target_link_ref, join, type)
    #     else:
    #         hub_name = target_link_ref.entity_cls.get_hub_name()
    #         sor_fk = 'fk_{}{}'.format(type, hub_name)
    #         type = source_entity
    #         self.map_sor_fk(sor_fk, target_link_ref, join, type)

    def map_field(self, source: Union[str, 'ConstantValue'], target: 'Column' = None, transform_func: 'FieldTransformation' = None, ref: str = '', type: str = '') -> None:
        if not target:
            return
        sat = target.get_table()
        sat_name = sat.cls_get_name()
        sat_mapping = SorSatMapping(self.source, sat, type)
        if not sat_mapping.name in self.sat_mappings:
            self.sat_mappings[sat_mapping.name] = sat_mapping
        else:
            sat_mapping = self.sat_mappings[sat_mapping.name]
        sat_mapping.map_field(source, target, transform_func, ref)
        sat_mapping.type = type

    def map_entity_old(self, entity_cls: HubEntity,  bk: str = '', join: str = '', type: str = ''):
        # is_hybrid = False
        hub_name = entity_cls.cls_get_hub_name()
        hub = entity_cls.cls_get_hub()

        if bk:
            source_field = '_id' #type: str
            source_col = Column(source_field, 'integer', tbl=hub) #type: Column
        # elif is_hybrid:
        #     source_field = 'fk_{}{}'.format(type, hub_name)
        #     source_col = Column(source_field, 'integer', tbl=self.sor_table)
        else:
            # source_field = 'fk_' + hub_name
            source_field = 'fk_{}{}'.format(type, hub_name)
            source_col = Column(source_field, 'integer', tbl=self.sor_table_name)

        # target_field = '_fk_' + hub_name #type: str
        target_field = 'fk_{}'.format(hub_name)
        target_field = self.get_fk_name(entity_cls)
        # if target_field in self.hubs:
        #     target_field = '_fk_parent_' + self.type + hub_name
        target_col = Column(target_field, 'integer', tbl=hub)
        field_mapping = LinkFieldMapping(source_col, target_col)
        field_mapping.bk = bk
        field_mapping.join = join
        self.hubs[target_field] = hub
        self.field_mappings.append(field_mapping)

    # def map_source(self, source, target: 'HubEntity'):
    #     source_col = Column(source, 'integer', tbl=self.sor_table)
    #     target_field = """_fk_source_{}""".format(target.get_hub_name())
    #     target_col = Column(target_field, 'integer', tbl=target.hub)
    #     field_mapping = LinkFieldMapping(source_col, target_col)
    #     self.hubs[target_field] = target.hub
    #     self.field_mappings.append(field_mapping)
    #
    # def map_target(self, source, target: 'HubEntity'):
    #     source_col = Column(source, 'integer', tbl=self.sor_table)
    #     target_field = """_fk_target_{}""".format(target.get_hub_name())
    #     target_col = Column(target_field, 'integer', tbl=target.hub)
    #     field_mapping = LinkFieldMapping(source_col, target_col)
    #     # field_mapping.bk = bk
    #     # field_mapping.join = join
    #     self.hubs[target_field] = target.hub
    #     self.field_mappings.append(field_mapping)
    #
    #     # source_col = Column(source, 'integer', tbl=self.sor_table)
    #     # target_field = target.__qualname__
    #     # mro = target.__mro__
    #     # currentframe = inspect.currentframe()
    #     # fs = inspect.getouterframes(currentframe)
    #     # target_field = self.get_fk_name(target)
    #     # # if target_field in self.hubs:
    #     # #     target_field = '_fk_parent_' + self.type + hub_name
    #     # target_col = Column(target_field, 'integer', tbl=target.hub)
    #     # field_mapping = LinkFieldMapping(source_col, target_col)
    #     # # field_mapping.bk = bk
    #     # # field_mapping.join = join
    #     # self.hubs[target_field] = target.hub
    #     # self.field_mappings.append(field_mapping) class SourceToSorMapping(BaseTableMapping):
    def __init__(self, source: Union['SourceTable', 'SourceQuery', 'File'], target: Union[str, Table], auto_map: bool = True, filter='', ignore_fields: List[str] = []) -> None:
        #todo transformations
        if isinstance(source, File):
            self.file_name = source.file_name
        elif isinstance(source, SourceTable):
            self.source_table = source
        elif isinstance(source, SourceQuery):
            self.source_table = source

        if isinstance(target, str):
            self.sor_table = str(target) #type: str
        else:
            target_tbl = cast(Table, target)
            self.sor_table = target_tbl.name
        super().__init__(source, target, filter)
        self.temp_table = self.sor_table.replace('_hstage', '') + '_temp'
        #todo keys
        self.keys = [] #type: List[str]
        ignore_fields = [s.lower() for s in ignore_fields]
        self.ignore_fields = ignore_fields
        # self.field_mappings = [] #type: List[FieldMapping]
        self.auto_map = auto_map
        if auto_map: self.create_auto_mappings(source, ignore_fields)



    def map_field(self, source: str, target: str = '', transform_func: 'FieldTransformation'=None, ref: str = '') -> None:
        super().map_field(source, target, transform_func)
        if source in self.source.key_names:
            self.keys.append(source)

    # def map_pk(self, source: str, target: str = '', transform_func: 'FieldTransformation'=None, ref: str = '') -> None:

    def create_auto_mappings(self, source: Union['SourceTable', 'SourceQuery', 'File'], ignore_fields: List[str] = []):
        if isinstance(source, File):
            field_names = source.get_header()
            for fld_name in field_names:
                if fld_name in ignore_fields:
                    continue
                self.map_field(fld_name, fld_name)
        elif isinstance(source, SourceQuery):
            if not source.is_reflected:
                source.reflect()
            for col in source.columns:
                if col.name in ignore_fields:
                    continue
                self.map_field(col.name, col.name)
        elif isinstance(source, SourceTable):
            if not source.is_reflected:
                source.reflect()
            for col in source.columns:
                if col.name in ignore_fields:
                    continue
                self.map_field(col.name, col.name)
        self.keys = [name.lower() for name in source.key_names]


    def get_fields(self, alias: str = '') -> str:
        return super().get_target_fields(alias)

    def get_fields_compare(self, source_alias: str='', target_alias: str='') -> str:
        if not source_alias: source_alias = 'tmp'
        if not target_alias: target_alias = 'hstg'
        return super().get_fields_compare(source_alias, target_alias)

    def get_keys(self, alias: str='') -> str:
        if not alias:
            return ','.join(self.keys)
        else:
            keys = ''
            for key in self.keys:
                keys += '{}.{},'.format(alias, key)
                keys = keys[:-1]
            return keys

    def get_keys_compare(self,    source_alias: str = '', target_alias: str = '') -> str:
        if not source_alias: source_alias = 'tmp'
        if not target_alias: target_alias = 'hstg'
        keys_compare = ''
        for key in self.keys:
            keys_compare += '{0}.{2} = {1}.{2} AND '.format(source_alias, target_alias, key)
        keys_compare = keys_compare[:-4]
        return keys_compare

    def get_source_encoding(self):
        #postgres valid name
        file_encoding = 'UTF-8'
        if isinstance(self.source, File):
            file_encoding = self.source.encoding.lower()
            if file_encoding == 'ascii' or file_encoding == 'latin-1':
                # conversie naar geldige postgres var
                file_encoding = 'LATIN1'
        return file_encoding

    def get_delimiter(self):
        delimiter = ';'
        if isinstance(self.source, File):
            delimiter = self.source.delimiter.lower() or ';'
        return delimiter

    def get_quote(self):
        quote = '|'
        if isinstance(self.source, File):
            quote = self.source.quote.lower() or '|'
        return quote class CsvFile(File):
    def __init__(self, file_name, **kwargs):
        super().__init__(file_name )
        self.quote = '"'
        self.delimiter = ';'
        self.file_kwargs = {}
        self.csv_kwargs = {}
        self.csv_kwargs['delimiter'] = self.delimiter
        for k,v in kwargs.items():
            if k == 'encoding':
                self.file_kwargs[k] = v
                if v == 'utf-8-sig':
                    v = 'utf8'
                self.encoding = v
            elif k == 'delimiter':
                self.csv_kwargs[k] = v
                self.delimiter = v
            elif k == 'quote':
                self.quote = v
        self.kwargs = kwargs

    def reflect(self):
        # lees eerste regel
        with open(self.file_name, 'r', **self.file_kwargs) as csvfile:
            reader = csv.reader(csvfile, **self.csv_kwargs)
            column_names = next(reader, None)
            for name in column_names:
                name = Column.clear_name(name)
                col = Column(name.lower())
                self.columns.append(col)
        self.is_reflected = True
from tests.unit_tests_basic._domainmodel import Patient, Traject, Patient_Traject_Link, SubTraject, Handeling, Zorginstelling, Zorgverzekeraar, Locatie, Hulpverlener, PatientHandelingLink
from main import get_root_path
from pyelt.helpers.mappingcreator import MappingWriter
from pyelt.mappings.base import ConstantValue
from pyelt.mappings.sor_to_dv_mappings import SorToEntityMapping, SorToLinkMapping
from pyelt.mappings.source_to_sor_mappings import SourceToSorMapping
from pyelt.sources.files import CsvFile


def init_source_to_sor_mappings():
    mappings = []
    source_file = CsvFile(get_root_path() + '/PYELT/tests/data/patienten1.csv', delimiter=';')
    source_file.reflect()
    source_file.set_primary_key(['patientnummer'])
    sor_mapping = SourceToSorMapping(source_file, 'patient_hstage', auto_map=True)
    mappings.append(sor_mapping)

    source_file = CsvFile(get_root_path() + '/PYELT/tests/data/zorgtrajecten1.csv', delimiter=';')
    source_file.reflect()
    source_file.set_primary_key(['patientnummer', 'trajectnummer'])
    sor_mapping = SourceToSorMapping(source_file, 'traject_hstage', auto_map=True)
    mappings.append(sor_mapping)

    source_file = CsvFile(get_root_path() + '/PYELT/tests/data/zorghandelingen1.csv', delimiter=';')
    source_file.reflect()
    source_file.set_primary_key(['patientnummer', 'datum', 'dbc_zorgactiviteit_code', 'hulpverlener_agb'])
    sor_mapping = SourceToSorMapping(source_file, 'handeling_hstage', auto_map=True)
    mappings.append(sor_mapping)
    # MappingWriter.create_python_code_mappings(source_file, remove_prefix='')
    return mappings

def init_tabsource_to_sor_mappings():
    mappings = []
    source_file = CsvFile(get_root_path() + '/PYELT/tests/data/patienten1_tab.csv', delimiter='\t')
    source_file.reflect()
    source_file.set_primary_key(['patientnummer'])
    sor_mapping = SourceToSorMapping(source_file, 'patient_hstage', auto_map=True)
    mappings.append(sor_mapping)
    return mappings

def init_sor_to_dv_mappings(sor):
    mappings = []
    mapping = SorToEntityMapping('patient_hstage', Patient, sor)
    mapping.map_bk("patientnummer || '_test'")
    mapping.map_field('achternaam', Patient.Personalia.achternaam)
    mapping.map_field('tussenvoegsels', Patient.Personalia.tussenvoegsels)
    mapping.map_field('voornaam', Patient.Personalia.voornaam)
    mapping.map_field('straat', Patient.Adres.straat)
    mapping.map_field('huisnummer::integer', Patient.Adres.huisnummer)
    mapping.map_field('huisnummertoevoeging', Patient.Adres.huisnummer_toevoeging)
    mapping.map_field('postcode')
    mapping.map_field('LEFT(hstg.postcode, 4)', Patient.Adres.postcode)
    mapping.map_field('plaats', Patient.Adres.plaats)
    mapping.map_field('geslacht')
    mapping.map_field('geboortedatum::date', Patient.Default.geboortedatum)
    mapping.map_field('inschrijvingsnummer', Patient.Inschrijving.inschrijfnummer)
    mapping.map_field('bsn', Patient.Inschrijving.bsn)
    mapping.map_field('inschrijvingsdatum::date', Patient.Inschrijving.inschrijfdatum)
    # hybrid sat mapping
    mapping.map_field('telefoon', Patient.Contactgegevens.telnummer, type=Patient.Contactgegevens.Types.telefoon)
    mapping.map_field('mobiel', Patient.Contactgegevens.telnummer, type=Patient.Contactgegevens.Types.mobiel)
    mappings.append(mapping)


    mapping = SorToEntityMapping('traject_hstage', SubTraject, sor)