import os
from os import path

from utils.db_handling.db_access import DbRequirementsAccessor, _get_cached_databases
from utils.helper_funcs_for_snakemake_workflow import convert_dbs_names_to_yaml_paths


def get_files_to_download_for_database(wildcards):
    file_dict = {}
    # snakemake will build the rule DAG, even if all required files are present. For databases with a date as
    # version, downloading a database from a date in the past is impossible. If the DbRequirementsAccessor is queried
    # with such an impossible db-version-combination, it wil raise an exception. As a workaround, we check for the
    # existence of the db_config.yaml and - if it exists - read the filenames from it.
    yaml = f"{wildcards.database}/{wildcards.version}/db_config.yaml"
    if path.exists(yaml):
        return {}
    else:    # if db_config.yaml does not exist
        db_info_obj = DbRequirementsAccessor(wildcards.database, wildcards.version)
        lst_files_to_dl_in_method_subdirs = db_info_obj.get_required_downloadable_files_in_method_subdirs()
        files_to_dl = []
        files_to_md5_check = []
        for f in lst_files_to_dl_in_method_subdirs:
            files_to_dl.append(path.join(
                wildcards.database,
                wildcards.version,
                f))
            # if *.md5 sums in files, add *.md5.checked to required files
            if f.endswith(".md5"):
                files_to_md5_check.append(path.join(
                    wildcards.database,
                    wildcards.version,
                    "processed",
                    path.basename(f) + ".checked"))
        file_dict["downloaded_files"] = files_to_dl
        file_dict["md5checks"] = files_to_md5_check
    return file_dict


def get_required_helper_db_yamls(wildcards):
    lst_yamls = []
    # snakemake will build the rule DAG, even if all required files are present. For databases with a date as
    # version, downloading a database from a date in the past is impossible. If the DbRequirementsAccessor is queried
    # with such an impossible db-version-combination, it wil raise an exception. As a workaround, we check for the
    # existence of the db_config.yaml and - if it exists - read the filenames from it.
    yaml = f"{wildcards.database}/{wildcards.version}/db_config.yaml"
    if path.exists(yaml):
        return []
    else:    # if db_config.yaml does not exist
        db_type = wildcards.database if not wildcards.database == 'eggnog' else f"{wildcards.database}_v{wildcards.version[0]}"
        db_info_obj = DbRequirementsAccessor(db_type, wildcards.version)
        if db_info_obj.is_requiring_helper_dbs():
            helper_db_names, versions = db_info_obj.get_required_dbs_and_versions()
            lst_yamls = convert_dbs_names_to_yaml_paths(helper_db_names, versions)
    return lst_yamls


rule create_db_cfg_yaml:
    input:
        unpack(get_files_to_download_for_database),
        required_helper_db_yamls=get_required_helper_db_yamls
    output:
        "{database}/{version}/db_config.yaml"
    message:
        "writing database configuration: {output[0]}"
    run:
        from utils.db_handling.db_access import DbYamlCreator
        db_yaml_creator = DbYamlCreator(yaml_out_path=output[0],
                                        required_db_yamls=input.required_helper_db_yamls)
        db_yaml_creator.write_cfg_file()
        os.sync() # make sure that files are written to filesystem before trying to read them again
        _ = _get_cached_databases(os.getcwd(), force_rebuild=True)
