# This file was auto generated by Styx.
# Do not edit this file directly.

import typing
import pathlib
from styxdefs import *

SPEC_FILE_MODIFY_METADATA = Metadata(
    id="445d6412e50c348caabba3213e8b6d10e9cc1ae4.workbench",
    name="spec-file-modify",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_SpecFileModifyAddParamsDictNoTag = typing.TypedDict('_SpecFileModifyAddParamsDictNoTag', {
    "structure": str,
    "file": str,
})
SpecFileModifyAddParamsDictTagged = typing.TypedDict('SpecFileModifyAddParamsDictTagged', {
    "@type": typing.Literal["add"],
    "structure": str,
    "file": str,
})
SpecFileModifyAddParamsDict = _SpecFileModifyAddParamsDictNoTag | SpecFileModifyAddParamsDictTagged


_SpecFileModifyRemoveParamsDictNoTag = typing.TypedDict('_SpecFileModifyRemoveParamsDictNoTag', {
    "filename": str,
    "suffix": bool,
    "recursive": bool,
})
SpecFileModifyRemoveParamsDictTagged = typing.TypedDict('SpecFileModifyRemoveParamsDictTagged', {
    "@type": typing.Literal["remove"],
    "filename": str,
    "suffix": bool,
    "recursive": bool,
})
SpecFileModifyRemoveParamsDict = _SpecFileModifyRemoveParamsDictNoTag | SpecFileModifyRemoveParamsDictTagged


_SpecFileModifyParamsDictNoTag = typing.TypedDict('_SpecFileModifyParamsDictNoTag', {
    "spec-file": str,
    "add": typing.NotRequired[list[SpecFileModifyAddParamsDict] | None],
    "remove": typing.NotRequired[list[SpecFileModifyRemoveParamsDict] | None],
})
SpecFileModifyParamsDictTagged = typing.TypedDict('SpecFileModifyParamsDictTagged', {
    "@type": typing.Literal["workbench/spec-file-modify"],
    "spec-file": str,
    "add": typing.NotRequired[list[SpecFileModifyAddParamsDict] | None],
    "remove": typing.NotRequired[list[SpecFileModifyRemoveParamsDict] | None],
})
SpecFileModifyParamsDict = _SpecFileModifyParamsDictNoTag | SpecFileModifyParamsDictTagged


def spec_file_modify_add(
    structure: str,
    file: str,
) -> SpecFileModifyAddParamsDictTagged:
    """
    Build parameters.
    
    Args:
        structure: the structure of the data file.
        file: the file to add.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "add",
        "structure": structure,
        "file": file,
    }
    return params


def spec_file_modify_add_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `SpecFileModifyAddParamsDict` object.
    
    Args:
        params: The parameters object to validate.
    """
    if params is None or not isinstance(params, dict):
        raise StyxValidationError(f'Params object has the wrong type \'{type(params)}\'')
    if params.get("structure", None) is None:
        raise StyxValidationError("`structure` must not be None")
    if not isinstance(params["structure"], str):
        raise StyxValidationError(f'`structure` has the wrong type: Received `{type(params.get("structure", None))}` expected `str`')
    if params.get("file", None) is None:
        raise StyxValidationError("`file` must not be None")
    if not isinstance(params["file"], str):
        raise StyxValidationError(f'`file` has the wrong type: Received `{type(params.get("file", None))}` expected `str`')


def spec_file_modify_add_cargs(
    params: SpecFileModifyAddParamsDict,
    execution: Execution,
) -> list[str]:
    """
    Build command-line arguments from parameters.
    
    Args:
        params: The parameters.
        execution: The execution object for resolving input paths.
    Returns:
        Command-line arguments.
    """
    cargs = []
    cargs.extend([
        "-add",
        params.get("structure", None),
        params.get("file", None)
    ])
    return cargs


def spec_file_modify_remove(
    filename: str,
    suffix: bool = False,
    recursive: bool = False,
) -> SpecFileModifyRemoveParamsDictTagged:
    """
    Build parameters.
    
    Args:
        filename: the filename to remove.
        suffix: match any file that ends with the given string (if there are\
            multiple matches, error unless -recursive was also specified).
        recursive: remove all files that match the string starting from any\
            folder.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "remove",
        "filename": filename,
        "suffix": suffix,
        "recursive": recursive,
    }
    return params


def spec_file_modify_remove_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `SpecFileModifyRemoveParamsDict` object.
    
    Args:
        params: The parameters object to validate.
    """
    if params is None or not isinstance(params, dict):
        raise StyxValidationError(f'Params object has the wrong type \'{type(params)}\'')
    if params.get("filename", None) is None:
        raise StyxValidationError("`filename` must not be None")
    if not isinstance(params["filename"], str):
        raise StyxValidationError(f'`filename` has the wrong type: Received `{type(params.get("filename", None))}` expected `str`')
    if params.get("suffix", False) is None:
        raise StyxValidationError("`suffix` must not be None")
    if not isinstance(params["suffix"], bool):
        raise StyxValidationError(f'`suffix` has the wrong type: Received `{type(params.get("suffix", False))}` expected `bool`')
    if params.get("recursive", False) is None:
        raise StyxValidationError("`recursive` must not be None")
    if not isinstance(params["recursive"], bool):
        raise StyxValidationError(f'`recursive` has the wrong type: Received `{type(params.get("recursive", False))}` expected `bool`')


def spec_file_modify_remove_cargs(
    params: SpecFileModifyRemoveParamsDict,
    execution: Execution,
) -> list[str]:
    """
    Build command-line arguments from parameters.
    
    Args:
        params: The parameters.
        execution: The execution object for resolving input paths.
    Returns:
        Command-line arguments.
    """
    cargs = []
    cargs.extend([
        "-remove",
        params.get("filename", None)
    ])
    if params.get("suffix", False):
        cargs.append("-suffix")
    if params.get("recursive", False):
        cargs.append("-recursive")
    return cargs


class SpecFileModifyOutputs(typing.NamedTuple):
    """
    Output object returned when calling `SpecFileModifyParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""


def spec_file_modify_params(
    spec_file: str,
    add: list[SpecFileModifyAddParamsDict] | None = None,
    remove: list[SpecFileModifyRemoveParamsDict] | None = None,
) -> SpecFileModifyParamsDictTagged:
    """
    Build parameters.
    
    Args:
        spec_file: the spec file to modify.
        add: add a file to the spec.
        remove: remove a file from the spec file.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/spec-file-modify",
        "spec-file": spec_file,
    }
    if add is not None:
        params["add"] = add
    if remove is not None:
        params["remove"] = remove
    return params


def spec_file_modify_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `SpecFileModifyParamsDict` object.
    
    Args:
        params: The parameters object to validate.
    """
    if params is None or not isinstance(params, dict):
        raise StyxValidationError(f'Params object has the wrong type \'{type(params)}\'')
    if params.get("spec-file", None) is None:
        raise StyxValidationError("`spec-file` must not be None")
    if not isinstance(params["spec-file"], str):
        raise StyxValidationError(f'`spec-file` has the wrong type: Received `{type(params.get("spec-file", None))}` expected `str`')
    if params.get("add", None) is not None:
        if not isinstance(params["add"], list):
            raise StyxValidationError(f'`add` has the wrong type: Received `{type(params.get("add", None))}` expected `list[SpecFileModifyAddParamsDict] | None`')
        for e in params["add"]:
            spec_file_modify_add_validate(e)
    if params.get("remove", None) is not None:
        if not isinstance(params["remove"], list):
            raise StyxValidationError(f'`remove` has the wrong type: Received `{type(params.get("remove", None))}` expected `list[SpecFileModifyRemoveParamsDict] | None`')
        for e in params["remove"]:
            spec_file_modify_remove_validate(e)


def spec_file_modify_cargs(
    params: SpecFileModifyParamsDict,
    execution: Execution,
) -> list[str]:
    """
    Build command-line arguments from parameters.
    
    Args:
        params: The parameters.
        execution: The execution object for resolving input paths.
    Returns:
        Command-line arguments.
    """
    cargs = []
    cargs.extend([
        "wb_command",
        "-spec-file-modify"
    ])
    cargs.append(params.get("spec-file", None))
    if params.get("add", None) is not None or params.get("remove", None) is not None:
        cargs.extend([
            *([a for c in [spec_file_modify_add_cargs(s, execution) for s in params.get("add", None)] for a in c] if (params.get("add", None) is not None) else []),
            *([a for c in [spec_file_modify_remove_cargs(s, execution) for s in params.get("remove", None)] for a in c] if (params.get("remove", None) is not None) else [])
        ])
    return cargs


def spec_file_modify_outputs(
    params: SpecFileModifyParamsDict,
    execution: Execution,
) -> SpecFileModifyOutputs:
    """
    Build outputs object containing output file paths and possibly stdout/stderr.
    
    Args:
        params: The parameters.
        execution: The execution object for resolving input paths.
    Returns:
        Outputs object.
    """
    ret = SpecFileModifyOutputs(
        root=execution.output_file("."),
    )
    return ret


def spec_file_modify_execute(
    params: SpecFileModifyParamsDict,
    runner: Runner | None = None,
) -> SpecFileModifyOutputs:
    """
    ADD OR REMOVE FILES FROM SPEC FILE.
    
    The input spec file is overwritten with the new version. If the spec file
    does not exist, it is created with default metadata.
    
    Removals are done before additions, so that you can remove files with a
    pattern, and then add new files even if they match that removal pattern.
    
    The <structure> argument of -add must match one of the following strings
    (you can use INVALID for cifti or volume files):CORTEX_LEFT
    CORTEX_RIGHT
    CEREBELLUM
    ACCUMBENS_LEFT
    ACCUMBENS_RIGHT
    ALL_GREY_MATTER
    ALL_WHITE_MATTER
    AMYGDALA_LEFT
    AMYGDALA_RIGHT
    BRAIN_STEM
    CAUDATE_LEFT
    CAUDATE_RIGHT
    CEREBELLAR_WHITE_MATTER_LEFT
    CEREBELLAR_WHITE_MATTER_RIGHT
    CEREBELLUM_LEFT
    CEREBELLUM_RIGHT
    CEREBRAL_WHITE_MATTER_LEFT
    CEREBRAL_WHITE_MATTER_RIGHT
    CORTEX
    DIENCEPHALON_VENTRAL_LEFT
    DIENCEPHALON_VENTRAL_RIGHT
    HIPPOCAMPUS_LEFT
    HIPPOCAMPUS_RIGHT
    HIPPOCAMPUS_DENTATE_LEFT
    HIPPOCAMPUS_DENTATE_RIGHT
    INVALID
    OTHER
    OTHER_GREY_MATTER
    OTHER_WHITE_MATTER
    PALLIDUM_LEFT
    PALLIDUM_RIGHT
    PUTAMEN_LEFT
    PUTAMEN_RIGHT
    THALAMUS_LEFT
    THALAMUS_RIGHT
    .
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `SpecFileModifyOutputs`).
    """
    spec_file_modify_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(SPEC_FILE_MODIFY_METADATA)
    params = execution.params(params)
    cargs = spec_file_modify_cargs(params, execution)
    ret = spec_file_modify_outputs(params, execution)
    execution.run(cargs)
    return ret


def spec_file_modify(
    spec_file: str,
    add: list[SpecFileModifyAddParamsDict] | None = None,
    remove: list[SpecFileModifyRemoveParamsDict] | None = None,
    runner: Runner | None = None,
) -> SpecFileModifyOutputs:
    """
    ADD OR REMOVE FILES FROM SPEC FILE.
    
    The input spec file is overwritten with the new version. If the spec file
    does not exist, it is created with default metadata.
    
    Removals are done before additions, so that you can remove files with a
    pattern, and then add new files even if they match that removal pattern.
    
    The <structure> argument of -add must match one of the following strings
    (you can use INVALID for cifti or volume files):CORTEX_LEFT
    CORTEX_RIGHT
    CEREBELLUM
    ACCUMBENS_LEFT
    ACCUMBENS_RIGHT
    ALL_GREY_MATTER
    ALL_WHITE_MATTER
    AMYGDALA_LEFT
    AMYGDALA_RIGHT
    BRAIN_STEM
    CAUDATE_LEFT
    CAUDATE_RIGHT
    CEREBELLAR_WHITE_MATTER_LEFT
    CEREBELLAR_WHITE_MATTER_RIGHT
    CEREBELLUM_LEFT
    CEREBELLUM_RIGHT
    CEREBRAL_WHITE_MATTER_LEFT
    CEREBRAL_WHITE_MATTER_RIGHT
    CORTEX
    DIENCEPHALON_VENTRAL_LEFT
    DIENCEPHALON_VENTRAL_RIGHT
    HIPPOCAMPUS_LEFT
    HIPPOCAMPUS_RIGHT
    HIPPOCAMPUS_DENTATE_LEFT
    HIPPOCAMPUS_DENTATE_RIGHT
    INVALID
    OTHER
    OTHER_GREY_MATTER
    OTHER_WHITE_MATTER
    PALLIDUM_LEFT
    PALLIDUM_RIGHT
    PUTAMEN_LEFT
    PUTAMEN_RIGHT
    THALAMUS_LEFT
    THALAMUS_RIGHT
    .
    
    Args:
        spec_file: the spec file to modify.
        add: add a file to the spec.
        remove: remove a file from the spec file.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `SpecFileModifyOutputs`).
    """
    params = spec_file_modify_params(
        spec_file=spec_file,
        add=add,
        remove=remove,
    )
    return spec_file_modify_execute(params, runner)


__all__ = [
    "SPEC_FILE_MODIFY_METADATA",
    "SpecFileModifyAddParamsDict",
    "SpecFileModifyAddParamsDictTagged",
    "SpecFileModifyOutputs",
    "SpecFileModifyParamsDict",
    "SpecFileModifyParamsDictTagged",
    "SpecFileModifyRemoveParamsDict",
    "SpecFileModifyRemoveParamsDictTagged",
    "spec_file_modify",
    "spec_file_modify_add",
    "spec_file_modify_execute",
    "spec_file_modify_params",
    "spec_file_modify_remove",
]
