"""Several dictionaries used to generate `.toml` configuration files copied under `/home/.marisco` folder and associated utilities function. These `.toml` files can be then adapted to your specific needs if required."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/configs.ipynb.

# %% auto 0
__all__ = ['AVOGADRO', 'NC_DIM', 'NC_VARS', 'CSV_VARS', 'NC_GROUPS', 'SMP_TYPE_LUT', 'NC_DTYPES', 'CSV_DTYPES', 'CFG_FNAME',
           'NUCLIDE_LOOKUP_FNAME', 'MARISCO_CFG_DIRNAME', 'CONFIGS', 'CONFIGS_CDL', 'NETCDF_TO_PYTHON_TYPE',
           'base_path', 'cfg', 'lut_path', 'cache_path', 'nuc_lut_path', 'species_lut_path', 'bodyparts_lut_path',
           'lab_lut_path', 'biogroup_lut_path', 'sediments_lut_path', 'unit_lut_path', 'detection_limit_lut_path',
           'filtered_lut_path', 'area_lut_path', 'prepmet_lut_path', 'sampmet_lut_path', 'counmet_lut_path',
           'nc_tpl_name', 'nc_tpl_path', 'get_time_units', 'sanitize', 'get_lut', 'Enums']

# %% ../nbs/api/configs.ipynb 2
from pathlib import Path
import os
import re
from typing import Dict, Callable
import pandas as pd
import fastcore.all as fc
from netCDF4 import Dataset
from .inout import read_toml

# %% ../nbs/api/configs.ipynb 3
AVOGADRO = 6.02214076e23

# %% ../nbs/api/configs.ipynb 4
NC_DIM = 'id'

# %% ../nbs/api/configs.ipynb 6
# Lookup variables names to MARIS NetCDF4 template variable names
NC_VARS = {
    'ID': 'id',
    'LON': 'lon',
    'LAT': 'lat',
    'SMP_DEPTH': 'smp_depth',
    'TOT_DEPTH': 'tot_depth',
    'TIME': 'time',
    'AREA': 'area',
    'SMP_ID': 'smp_id',
    'NUCLIDE': 'nuclide',
    'VALUE': 'value',
    'UNIT': 'unit',
    'UNC': 'unc',
    'DL': 'dl',
    'DLV': 'dlv',
    'FILT': 'filt',
    'COUNT_MET': 'count_met',
    'SAMP_MET': 'samp_met',
    'PREP_MET': 'prep_met',
    #'DRY_MET': 'dry_met', # NOT IN USE, no LUT for this. 
    'VOL': 'vol',
    'SAL': 'sal',
    'TEMP': 'temp',
    'PH': 'ph',
    'BIO_GROUP': 'bio_group',
    'SPECIES': 'species',
    'BODY_PART': 'body_part',
    'SED_TYPE': 'sed_type',
    'TOP': 'top',
    'BOTTOM': 'bottom',
    'DRYWT': 'drywt',
    'WETWT': 'wetwt',
    'PERCENTWT': 'percentwt',
    'LAB': 'lab',
    'PROFILE_ID': 'profile_id', # NEED TO INCLUDE.
    'STATION': 'station'
    }

# %% ../nbs/api/configs.ipynb 8
CSV_VARS = {
    'LON': 'longitude', 
    'LAT': 'latitude',
    'SMP_DEPTH': 'sampdepth',
    'TOT_DEPTH': 'totdepth',
    'TIME': 'begperiod',
    'AREA': 'area',
    'NUCLIDE': 'nuclide_id',
    'VALUE': 'activity',
    'UNIT': 'unit_id',
    'UNC': 'uncertaint',
    'DL': 'detection',
    'DLV': 'detection_val',
    'FILT': 'filtered',
    'COUNT_MET': 'counmet_id',
    #'DRY_MET': 'drymet_id', # NOT IN USE, no LUT for this. 
    'SAMP_MET': 'sampmet_id', 
    'PREP_MET': 'prepmet_id',
    'VOL': 'volume',
    'SAL': 'salinity',
    'TEMP': 'temperatur',
    'SPECIES': 'species_id',    
    'BODY_PART': 'bodypar_id',
    'SED_TYPE': 'sedtype_id',
    'TOP': 'sliceup',
    'BOTTOM': 'slicedown',
    'DRYWT': 'drywt',
    'WETWT': 'wetwt',
    'PERCENTWT': 'percentwt',
    'LAB': 'lab_id',
    'PROFILE_ID': 'profile_id', # NEED TO INCLUDE.
    'SAMPLE_TYPE': 'samptype_id', # NEED TO INCLUDE. 
    'TAXONNAME': 'taxonname',
    'TAXONREPNAME': 'taxonrepname',
    'TAXONRANK': 'taxonrank',
    'TAXONDB': 'taxondb',
    'TAXONDBID': 'taxondb_id',
    'TAXONDBURL': 'taxondb_url',
    'REF_ID': 'ref_id',
    'SMP_ID': 'samplabcode',
    'STATION': 'station'

    # CSV_VARS not included in current workflow.
    # 'SAMPLE_LAB_CODE': 'samplelabcode',
    # 'SED_REPNAME': 'sedrepname',
    # 'MEASURE_NOTE': 'measurenote',
    # 'REFERENCE_NOTE': 'referencenote',
    # 'SAMPLE_NOTE': 'samplenote',
}

# %% ../nbs/api/configs.ipynb 9
NC_GROUPS = {'BIOTA': 'biota',
             'SEAWATER': 'seawater',
             'SEDIMENT': 'sediment',
             'SUSPENDED_MATTER': 'suspended_matter'}

# %% ../nbs/api/configs.ipynb 10
SMP_TYPE_LUT = {
    'SEAWATER': 1,
    'BIOTA': 2,
    'SEDIMENT': 3,
    'SUSPENDED_MATTER': 4
}

# %% ../nbs/api/configs.ipynb 11
NC_DTYPES = {
    'AREA': {
        'name': 'area_t', 
        'fname': 'dbo_area.xlsx',
        'key': 'displayName', 
        'value':'areaId'
    },
    'BIO_GROUP': {
        'name': 'bio_group_t', 
        'fname': 'dbo_biogroup.xlsx',
        'key': 'biogroup', 
        'value':'biogroup_id'
    },
    'BODY_PART': {
        'name': 'body_part_t', 
        'fname': 'dbo_bodypar.xlsx',
        'key': 'bodypar', 
        'value':'bodypar_id'
    },
    'COUNT_MET': {
        'name': 'count_met_t', 
        'fname': 'dbo_counmet.xlsx',
        'key': 'counmet',
        'value':'counmet_id'
    },
    'DL': {
        'name': 'dl_t', 
        'fname': 'dbo_detectlimit.xlsx',
        'key': 'name_sanitized', 
        'value':'id'
    },
    'FILT': {
        'name': 'filt_t', 
        'fname': 'dbo_filtered.xlsx',
        'key': 'name',
        'value':'id'
    },
    'NUCLIDE': {
        'name': 'nuclide_t', 
        'fname': 'dbo_nuclide.xlsx',
        'key': 'nc_name',
        'value':'nuclide_id'
    },
    'PREP_MET': {
        'name': 'prep_met_t', 
        'fname': 'dbo_prepmet.xlsx', 
        'key': 'prepmet',
        'value':'prepmet_id'
    },
    'SAMP_MET': {
        'name': 'samp_met_t', 
        'fname': 'dbo_sampmet.xlsx', 
        'key': 'sampmet',
        'value':'sampmet_id'
    },
    'SED_TYPE': {
        'name': 'sed_type_t', 
        'fname': 'dbo_sedtype.xlsx', 
        'key': 'sedtype', 
        'value':'sedtype_id'
    },
    'SPECIES': {
        'name': 'species_t', 
        # 'fname': 'dbo_species_cleaned.xlsx',
        'fname': 'dbo_species_2024_11_19.xlsx',
        'key': 'species', 
        'value':'species_id'
    },
    'UNIT': {
        'name': 'unit_t', 
        'fname': 'dbo_unit.xlsx', 
        'key': 'unit_sanitized', 
        'value':'unit_id'
    },
    'LAB': {
        'name': 'lab_t', 
        #'fname': 'dbo_lab.xlsx', 
        'fname': 'dbo_lab_cleaned.xlsx', 
        'key': 'lab', 
        'value':'lab_id'
    }
}


# %% ../nbs/api/configs.ipynb 12
CSV_DTYPES = {
    'AREA': {'state': 'decoded'},
    'NUCLIDE': {'state': 'encoded'},  # encoded nuclide_id
    'UNIT': {'state': 'encoded'},  # encoded unit_id
    'DL': {'state': 'decoded'},
    'FILT': {'state': 'decoded'},
    'COUNT_MET': {'state': 'encoded'},  # encoded counmet_id
    'SAMP_MET': {'state': 'encoded'},  # encoded sampmet_id
    'PREP_MET': {'state': 'encoded'},  # encoded prepmet_id
    'SPECIES': {'state': 'encoded'},  # encoded species_id
    'BODY_PART': {'state': 'encoded'},  # encoded bodypar_id
    'SED_TYPE': {'state': 'encoded'},  # encoded sedtype_id
    'LAB': {'state': 'encoded'},  # encoded lab_id
}

# %% ../nbs/api/configs.ipynb 13
CFG_FNAME = 'configs.toml'
#CDL_FNAME = 'cdl.toml'
NUCLIDE_LOOKUP_FNAME = 'dbo_nuclide.xlsx'
MARISCO_CFG_DIRNAME = '.marisco'

# %% ../nbs/api/configs.ipynb 14
def base_path(): 
    "Return the path to the `.marisco` folder under your home directory."
    return Path.home() / MARISCO_CFG_DIRNAME

# %% ../nbs/api/configs.ipynb 17
CONFIGS = {
    'gh': {
        'owner': 'franckalbinet',
        'repo': 'marisco'
    },
    'names': {  
        'nc_template': 'maris-template.nc'
    },
    'dirs': {
        'lut': str(base_path() / 'lut'), # Look-up tables
        'cache': str(base_path() / 'cache'), # Cache (e.f WoRMS species)
        'tmp': str(base_path() / 'tmp')
    },
    'paths': {
        'nc_template': 'nbs/files/nc',
        'luts': 'nbs/files/lut'
    },
    # TO BE REMOVED:Now read directly from `maris.cdl` file
    # 'units': {
    #     'time': 'seconds since 1970-01-01 00:00:00.0'
    # },
    'zotero': {
        'api_key': os.getenv('ZOTERO_API_KEY'),
        'lib_id': '2432820'
    }
}

# %% ../nbs/api/configs.ipynb 21
def cfg(): 
    "Return the configuration as a dictionary."
    return read_toml(base_path() / CFG_FNAME)

# %% ../nbs/api/configs.ipynb 22
def lut_path(): 
    "Return the path to the lookup tables directory."
    return Path(cfg()['dirs']['lut'])

# %% ../nbs/api/configs.ipynb 23
def cache_path(): 
    "Return the path to the cache directory."
    return Path(cfg()['dirs']['cache'])

# %% ../nbs/api/configs.ipynb 24
# TO BE REMOVED: Now read directly from `maris.cdl` file
CONFIGS_CDL = { 
    'placeholder': '_to_be_filled_in_',
    'grps': {
        'sea': {
            'name': 'seawater',
            'id': 1
        },
        'bio': {
            'name': 'biota',
            'id': 2
        },
        'sed': {
            'name': 'sediment',
            'id': 3
        },
        'sus': {
            'name': 'suspended-matter',
            'id': 4
        }
    },
    'global_attrs': {
        # Do not update keys. Only values if required
        'id': '', # zotero?
        'title': '',
        'summary': '',
        'keywords': '',
        'keywords_vocabulary': 'GCMD Science Keywords',
        'keywords_vocabulary_url': 'https://gcmd.earthdata.nasa.gov/static/kms/',
        'record': '',
        'featureType': '',
        'cdm_data_type': '',

        # Conventions
        'Conventions': 'CF-1.10 ACDD-1.3',

        # Publisher [ACDD1.3]
        'publisher_name': 'Paul MCGINNITY, Iolanda OSVATH, Florence DESCROIX-COMANDUCCI',
        'publisher_email': 'p.mc-ginnity@iaea.org, i.osvath@iaea.org, F.Descroix-Comanducci@iaea.org', 
        'publisher_url': 'https://maris.iaea.org',
        'publisher_institution': 'International Atomic Energy Agency - IAEA', 

        # Creator info [ACDD1.3]
        'creator_name': '',
        'institution': '',
        'metadata_link': '',
        'creator_email': '',
        'creator_url': '',
        'references': '',
        'license': ' '.join(['Without prejudice to the applicable Terms and Conditions', 
                             '(https://nucleus.iaea.org/Pages/Others/Disclaimer.aspx),',
                             'I hereby agree that any use of the data will contain appropriate',
                             'acknowledgement of the data source(s) and the IAEA Marine',
                             'Radioactivity Information System (MARIS).']),
        'comment': '',
        # Dataset info & coordinates [ACDD1.3]
        #'project': '', # Network long name
        #'platform': '', # Should be a long / full name
        'geospatial_lat_min': '', 
        'geospatial_lon_min': '',
        'geospatial_lat_max': '',
        'geospatial_lon_max': '',
        'geospatial_vertical_min': '',
        'geospatial_vertical_max': '',
        'geospatial_bounds': '', # wkt representation
        'geospatial_bounds_crs': 'EPSG:4326',

        # Time information
        'time_coverage_start': '',
        'time_coverage_end': '',
        #'time_coverage_resolution': '',
        'local_time_zone': '',
        'date_created': '',
        'date_modified': '',
        #
        # -- Additional metadata (custom to MARIS)
        #
        'publisher_postprocess_logs': ''
        },
    'dim': {
        'name': 'sample',
        'attrs': {
            'long_name': 'Sample ID of measurement'
        },
        'dtype': 'u8'
    },
    'vars': {    
        'defaults': {
            'lon': {
                'name': 'lon',
                'attrs': {
                    'long_name': 'Measurement longitude',
                    'standard_name': 'longitude',
                    'units': 'degrees_north',
                    'axis': 'Y',
                    '_CoordinateAxisType': 'Lon'
                },
                'dtype': 'f4'
            },
            'lat': {
                'name': 'lat',
                'attrs': {
                    'long_name': 'Measurement latitude',
                    'standard_name': 'latitude',
                    'units': 'degrees_east',
                    'axis': 'X',
                    '_CoordinateAxisType': 'Lat'
                },
                'dtype': 'f4'
            },
            'smp_depth': {
                'name': 'smp_depth',
                'attrs': {
                    'long_name': 'Sample depth below seal level',
                    'standard_name': 'sample_depth_below_sea_floor',
                    'units': 'm',
                    'axis': 'Z'
                },
                'dtype': 'f4'
            },
            'tot_depth': {
                'name': 'tot_depth',
                'attrs': {
                    'long_name': 'Total depth below seal level',
                    'standard_name': 'total_depth_below_sea_floor',
                    'units': 'm',
                    'axis': 'Z'
                },
                'dtype': 'f4'
            },
            'time': {
                'name': 'time',
                'attrs': {
                    'long_name': 'Time of measurement',
                    'standard_name': 'time',
                    'units': 'seconds since 1970-01-01 00:00:00.0',
                    'time_origin': '1970-01-01 00:00:00',
                    'time_zone': 'UTC',
                    'abbreviation': 'Date/Time',
                    'axis': 'T',
                    'calendar': 'gregorian'
                },
                'dtype': 'u8',
            },
            'area': {
                'name': 'area',
                'attrs': {
                    'long_name': 'Marine area/region id',
                    'standard_name': 'area_id'
                },
                'dtype': 'area_t'
            },
        },
        'bio': {
            'bio_group': {
                'name': 'bio_group',
                'attrs': {
                    'long_name': 'Biota group',
                    'standard_name': 'biota_group_tbd'
                },
                'dtype': 'bio_group_t'
            },
            'species': {
                'name': 'species',
                'attrs': {  
                    'long_name': 'Species',
                    'standard_name': 'species'
                },
                'dtype': 'species_t'
            },
            'body_part': {
                'name': 'body_part',
                'attrs': {
                    'long_name': 'Body part',
                    'standard_name': 'body_part_tbd'
                },
                'dtype': 'body_part_t' 
            }
        },
        'sed': {
            'sed_type': {
                'name': 'sed_type',
                'attrs': {
                    'long_name': 'Sediment type',
                    'standard_name': 'sediment_type_tbd'
                },
                'dtype': 'sed_type_t'
            },
            'top': {
                'name': 'top',
                'attrs': {
                    'long_name': 'Top depth of sediment layer',
                    'standard_name': 'top_depth_of_sediment_layer_tbd'
                },
                'dtype': 'f4'
            },
            'bottom': {
                'name': 'bottom',
                'attrs': {
                    'long_name': 'Bottom depth of sediment layer',
                    'standard_name': 'bottom_depth_of_sediment_layer_tbd'
                },
                'dtype': 'f4'
            },
        },
        'suffixes':  {
            'uncertainty': {
                'name': '_unc',
                'attrs': {
                    'long_name': ' uncertainty',
                    'standard_name': '_uncertainty'
                },
                'dtype': 'f4'
            },
            'detection_limit': {
                'name': '_dl',
                'attrs': {
                    'long_name': ' detection limit',
                    'standard_name': '_detection_limit'
                },
                'dtype': 'dl_t'
            },
            'volume': {
                'name': '_vol',
                'attrs': {
                    'long_name': ' volume',
                    'standard_name': '_volume'
                },
                'dtype': 'f4'
            },
            'salinity': {
                'name': '_sal',
                'attrs': {
                    'long_name': ' salinity',
                    'standard_name': '_sal'
                },
                'dtype': 'f4'
            },
            'temperature': {
                'name': '_temp',
                'attrs': {
                    'long_name': ' temperature',
                    'standard_name': '_temp'
                },
                'dtype': 'f4'
            },
            'filtered': {
                'name': '_filt',
                'attrs': {
                    'long_name': ' filtered',
                    'standard_name': '_filtered'
                },
                'dtype': 'filt_t'
            },
            'counting_method': {
                'name': '_counmet',
                'attrs': {
                    'long_name': ' counting method',
                    'standard_name': '_counting_method'
                },
                'dtype': 'counmet_t'
            },
            'sampling_method': {
                'name': '_sampmet',
                'attrs': {
                    'long_name': ' sampling method',
                    'standard_name': '_sampling_method'
                },
                'dtype': 'sampmet_t'
            },
            'preparation_method': {
                'name': '_prepmet',
                'attrs': {
                    'long_name': ' preparation method',
                    'standard_name': '_preparation_method'
                },
                'dtype': 'prepmet_t'
            },
            'unit': {
                'name': '_unit',
                'attrs': {
                    'long_name': ' unit',
                    'standard_name': '_unit'
                },
                'dtype': 'unit_t'
            }
        }
    },
    'enums': [
        {
            'name': 'area_t', 
            'fname': 'dbo_area.xlsx', 
            'key': 'displayName', 
            'value':'areaId'
        },
        {
            'name': 'bio_group_t', 
            'fname': 'dbo_biogroup.xlsx', 
            'key': 'biogroup', 
            'value':'biogroup_id'
        },
        {
            'name': 'body_part_t', 
            'fname': 'dbo_bodypar.xlsx', 
            'key': 'bodypar', 
            'value':'bodypar_id'
        },
        {
            'name': 'species_t', 
            'fname': 'dbo_species_cleaned.xlsx', 
            'key': 'species', 
            'value':'species_id'
        },
        {
            'name': 'sed_type_t', 
            'fname': 'dbo_sedtype.xlsx', 
            'key': 'sedtype', 
            'value':'sedtype_id'
        },  
        {
            'name': 'unit_t', 
            'fname': 'dbo_unit.xlsx', 
            'key': 'unit_sanitized', 
            'value':'unit_id'
        },
        {
            'name': 'dl_t', 
            'fname': 'dbo_detectlimit.xlsx', 
            'key': 'name_sanitized', 
            'value':'id'
        },
        {
            'name': 'filt_t', 
            'fname': 'dbo_filtered.xlsx', 
            'key': 'name',
            'value':'id'
        },
        {
            'name': 'counmet_t', 
            'fname': 'dbo_counmet.xlsx', 
            'key': 'counmet',
            'value':'counmet_id'
        },
        {
            'name': 'sampmet_t', 
            'fname': 'dbo_sampmet.xlsx', 
            'key': 'sampmet',
            'value':'sampmet_id'
        },
        {
            'name': 'prepmet_t', 
            'fname': 'dbo_prepmet.xlsx', 
            'key': 'prepmet',
            'value':'prepmet_id'
        }
        ]
}

# %% ../nbs/api/configs.ipynb 27
# def cdl_cfg():
#     "Return the CDL (Common Data Language) configuration as a dictionary."
#     try:
#         return read_toml(base_path() / CDL_FNAME)
#     except FileNotFoundError:
#         return CONFIGS_CDL

# %% ../nbs/api/configs.ipynb 28
# def grp_names(): 
#     "Return the group names as defined in `cdl.toml`."
#     return [v['name'] for v in cdl_cfg()['grps'].values()]

# %% ../nbs/api/configs.ipynb 30
def nuc_lut_path(): 
    "Return the path to the nuclide lookup table."
    return Path(cfg()['dirs']['lut']) / NUCLIDE_LOOKUP_FNAME

# %% ../nbs/api/configs.ipynb 31
def species_lut_path():
    "Return the path to the species lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['SPECIES']['fname']
    
    return src_dir / fname

# %% ../nbs/api/configs.ipynb 33
def bodyparts_lut_path():
    "Return the path to the body parts lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['BODY_PART']['fname']
    return src_dir / fname

# %% ../nbs/api/configs.ipynb 34
def lab_lut_path():
    "Return the path to the laboratory lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['LAB']['fname']
    return src_dir / fname

# %% ../nbs/api/configs.ipynb 36
def biogroup_lut_path():
    "Return the path to the biota group lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['BIO_GROUP']['fname']
    return src_dir / fname

# %% ../nbs/api/configs.ipynb 38
def sediments_lut_path():
    "Return the path to the sediment type lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['SED_TYPE']['fname']
    return src_dir / fname

# %% ../nbs/api/configs.ipynb 40
def unit_lut_path():
    "Return the path to the unit lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['UNIT']['fname']
    return src_dir / fname

# %% ../nbs/api/configs.ipynb 42
def detection_limit_lut_path():
    "Return the path to the detection limit lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['DL']['fname']
    return src_dir / fname

# %% ../nbs/api/configs.ipynb 44
def filtered_lut_path():
    "Return the path to the filtered lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['FILT']['fname']
    return src_dir / fname

# %% ../nbs/api/configs.ipynb 46
def area_lut_path():
    "Return the path to the area lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['AREA']['fname']
    return src_dir / fname

# area_lut_path()

# %% ../nbs/api/configs.ipynb 48
def prepmet_lut_path():
    "Return the path to the prepmet lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['PREP_MET']['fname']
    return src_dir / fname

# prepmet_lut_path()

# %% ../nbs/api/configs.ipynb 50
def sampmet_lut_path():
    "Return the path to the sampmet lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['SAMP_MET']['fname']
    return src_dir / fname

# sampmet_lut_path()

# %% ../nbs/api/configs.ipynb 52
def counmet_lut_path():
    "Return the path to the counmet lookup table."
    src_dir = lut_path()
    fname = NC_DTYPES['COUNT_MET']['fname']
    return src_dir / fname

# counmet_lut_path()

# %% ../nbs/api/configs.ipynb 55
NETCDF_TO_PYTHON_TYPE = {
    'u8': int,
    'f4': float
    }

# %% ../nbs/api/configs.ipynb 56
# def name2grp(
#     name: str, # Group name
#     cdl: dict, # CDL configuration
#     ):
#     # Reverse `cdl.toml` config group dict so that group config key can be retrieve based on its name
#     return {v['name']:k  for k, v in cdl['grps'].items()}[name]

# %% ../nbs/api/configs.ipynb 59
def nc_tpl_name():
    "Return the name of the MARIS NetCDF template as defined in `configs.toml`"
    p = base_path()
    return read_toml(p / 'configs.toml')['names']['nc_template']

# %% ../nbs/api/configs.ipynb 60
def nc_tpl_path():
    "Return the path of the MARIS NetCDF template as defined in `configs.toml`"
    p = base_path()
    return p / read_toml(p / 'configs.toml')['names']['nc_template']

# %% ../nbs/api/configs.ipynb 61
def get_time_units(
    nc_path: Callable=nc_tpl_path # Function returning Path to NetCDF template file
    ) -> str: # Time units string (e.g. 'seconds since 1970-01-01 00:00:00.0')
    "Get the units attribute of the time variable from a NetCDF file."
    with Dataset(nc_tpl_path(), 'r') as nc:
        for group in nc.groups.values():
            if 'time' in group.variables:
                return group.variables['time'].units
                
    raise ValueError("Time variable not found in NetCDF file")

# %% ../nbs/api/configs.ipynb 65
def sanitize(
    s: str|float # String or float to sanitize
    ) -> str|float:  # Sanitized string or original float
    """
    Sanitize dictionary key to comply with NetCDF enumeration type:
    
    - Remove `(`, `)`, `.`, `/`, `-`
    - Strip the string
    - Return original value if it's not a string (e.g., NaN)
    """
    if isinstance(s, str):
        s = re.sub(r'[().]', '', s)
        return re.sub(r'[/-]', ' ', s).strip()
    elif pd.isna(s):  # This covers np.nan, None, and pandas NaT
        return s
    else:
        return str(s).strip()

# %% ../nbs/api/configs.ipynb 69
def try_int(x):
    "Try to convert `x` to an integer."
    try:
        return int(x)
    except (ValueError, TypeError):
        return x

# %% ../nbs/api/configs.ipynb 70
def get_lut(
    src_dir: str, # Directory containing lookup tables
    fname: str, # Excel file lookup table name
    key: str, # Excel file column name to be used as dict keys 
    value: str, # Excel file column name to be used as dict values 
    do_sanitize: bool=True, # Sanitization required?
    reverse: bool=False, # Reverse lookup table (value, key)
    check_duplicates: bool=False # Check for duplicates in lookup table
    ) -> Dict[str, int]: # MARIS lookup table (key, value)
    "Convert MARIS db lookup table excel file to dictionary `{'name': id, ...}` or `{id: name, ...}` if `reverse` is True."
    fname = Path(src_dir) / fname
    df = pd.read_excel(fname, usecols=[key, value]).dropna(subset=value)
    
    if check_duplicates:
        duplicates = df[key][df[key].duplicated()].tolist()
        if duplicates: print(f"Warning: {fname.name}: found duplicate keys: {duplicates}")
        
    df[value] = df[value].astype('int')
    df = df.set_index(key)
    lut = df[value].to_dict()
    if do_sanitize: lut = {sanitize(k): v for k, v in lut.items()}
    lut = {try_int(k): try_int(v) for k, v in lut.items()}    
    return {v: k for k, v in lut.items()} if reverse else lut

# %% ../nbs/api/configs.ipynb 73
class Enums():
    "Return dictionaries of MARIS NetCDF's enumeration types."
    def __init__(self, 
                 lut_src_dir: str, # Directory containing lookup tables
                 dtypes: Dict[str, Dict[str, str]]=NC_DTYPES, # Custom NetCDF types
                 ):
        fc.store_attr()
        self.types = self.lookup()
        
    def filter(self, var_name, values):
        return {name: id for name, id in self.types[var_name].items() if id in values}
    
    def lookup(self):
        types = {}
        for var_name, dtype in self.dtypes.items():
            name, fname, key, value = dtype.values()
            lut = get_lut(self.lut_src_dir, fname, key=key, value=value)
            types[var_name] = lut
        return types
