from snakebids import bids, generate_inputs
from pathlib import Path
from query_configs import load_app_config
from bidsapps.repo_management import  get_repo

configfile: 'config/snakebids.yml'

# Get input wildcards
inputs = generate_inputs(
    bids_dir=config["bids_dir"],
    pybids_inputs=config["pybids_inputs"],
    pybidsdb_dir=config.get("pybidsdb_dir"),
    pybidsdb_reset=config.get("pybidsdb_reset"),
    derivatives=config.get("derivatives", None),
    participant_label=config.get("participant_label", None),
    exclude_participant_label=config.get("exclude_participant_label", None),
    validate=not config.get("plugins.validator.skip", False)
)


bids_dir=config['bids_dir']

subj_wildcards = inputs.subj_wildcards

# get the subjects that have all the bids components (e.g. both t1 and dwi)
#   we do this by getting the first component, and then filtering with the entities of each additional one..
comps = list(inputs.keys())
bids_intersect = inputs[comps[0]]

if len(comps) > 0:
    for c in comps[1:]:
        bids_intersect = bids_intersect.filter(
            **inputs[c].entities[tuple(subj_wildcards.keys())]
        )


# Repository URL for app configurations
repo_url = get_repo()['repo_path']

# Dynamically load app configurations
apps_to_run = config["apps_to_run"]
app_configs = {app:load_app_config(repo_url, app) for app in apps_to_run}



rule all:
    input:
        expand('{app}/{app}.zip',
            app=apps_to_run)




for app in apps_to_run:


    if "container" in app_configs[app]:

        rule:
            name:
                f"get_container_{app}"
            container:
                app_configs[app]['container']
            output:
                f"resources/containers/{app}.sif",
            localrule: True
            shell:
                "ln -sv $SINGULARITY_CONTAINER {output}"

        rule:
            name:
                f"{app}"
            input:
                bids=bids_dir,
                container="resources/containers/{app}.sif",
            params:
                default_opts = app_configs[app]['opts'],
                analysis_level=app_configs[app]['analysis_level']

            output:
                zipfile=bids(root=f'{{app,{app}}}',
                                suffix='out.zip',
                                **bids_intersect.input_wildcards)
            resources:            
                **{key:val for key,val in app_configs[app]['resources'].items()}
            script:
                "scripts/container_runscript.py"

    #we have a snakebids app 
    else:

        rule:
            name:
                f"get_repo_{app}"
            params:
                url = app_configs[app]['url'],
                tag = app_configs[app]['tag'],
            output:
                repo=directory(f"resources/repos/{app}")
            localrule: True
            shell:
                "git clone {params.url} -b {params.tag} {output.repo}"


        rule:
            name:
                f"{app}"
            input:
                bids=bids_dir,
                repo="resources/repos/{app}",
            params:
                runscript = app_configs[app]['runscript'],
                default_opts = app_configs[app]['opts'],
                analysis_level=app_configs[app]['analysis_level']
            output:
                zipfile=bids(root=f'{{app,{app}}}',
                                suffix='out.zip',
                                **bids_intersect.input_wildcards)
            resources:
                **{key:val for key,val in app_configs[app]['resources'].items()}
            script:
                "scripts/snakebids_runscript.py"

    
    #add rule for combining zip files
    rule:
        name:
            f"{app}_combine"
        input:
            bids_intersect.expand(
                bids(root=f'{app}', 
                suffix='out.zip',
                **bids_intersect.input_wildcards))
        output:
            zipfile=f'{{app,{app}}}/{{app}}.zip',
        script:
            "scripts/merge_zip.py"



