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

import typing
import pathlib
from styxdefs import *

METRIC_VECTOR_OPERATION_METADATA = Metadata(
    id="2ed0edf6d0f6355b8d747c848ce1f1d204659400.workbench",
    name="metric-vector-operation",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_MetricVectorOperationParamsDictNoTag = typing.TypedDict('_MetricVectorOperationParamsDictNoTag', {
    "vectors-a": InputPathType,
    "vectors-b": InputPathType,
    "operation": str,
    "metric-out": str,
    "magnitude": bool,
    "normalize-output": bool,
    "normalize-b": bool,
    "normalize-a": bool,
})
MetricVectorOperationParamsDictTagged = typing.TypedDict('MetricVectorOperationParamsDictTagged', {
    "@type": typing.Literal["workbench/metric-vector-operation"],
    "vectors-a": InputPathType,
    "vectors-b": InputPathType,
    "operation": str,
    "metric-out": str,
    "magnitude": bool,
    "normalize-output": bool,
    "normalize-b": bool,
    "normalize-a": bool,
})
MetricVectorOperationParamsDict = _MetricVectorOperationParamsDictNoTag | MetricVectorOperationParamsDictTagged


class MetricVectorOperationOutputs(typing.NamedTuple):
    """
    Output object returned when calling `MetricVectorOperationParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    metric_out: OutputPathType
    """the output file"""


def metric_vector_operation_params(
    vectors_a: InputPathType,
    vectors_b: InputPathType,
    operation: str,
    metric_out: str,
    magnitude: bool = False,
    normalize_output: bool = False,
    normalize_b: bool = False,
    normalize_a: bool = False,
) -> MetricVectorOperationParamsDictTagged:
    """
    Build parameters.
    
    Args:
        vectors_a: first vector input file.
        vectors_b: second vector input file.
        operation: what vector operation to do.
        metric_out: the output file.
        magnitude: output the magnitude of the result (not valid for dot\
            product).
        normalize_output: normalize output vectors (not valid for dot product).
        normalize_b: normalize vectors of second input.
        normalize_a: normalize vectors of first input.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/metric-vector-operation",
        "vectors-a": vectors_a,
        "vectors-b": vectors_b,
        "operation": operation,
        "metric-out": metric_out,
        "magnitude": magnitude,
        "normalize-output": normalize_output,
        "normalize-b": normalize_b,
        "normalize-a": normalize_a,
    }
    return params


def metric_vector_operation_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `MetricVectorOperationParamsDict` 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("vectors-a", None) is None:
        raise StyxValidationError("`vectors-a` must not be None")
    if not isinstance(params["vectors-a"], (pathlib.Path, str)):
        raise StyxValidationError(f'`vectors-a` has the wrong type: Received `{type(params.get("vectors-a", None))}` expected `InputPathType`')
    if params.get("vectors-b", None) is None:
        raise StyxValidationError("`vectors-b` must not be None")
    if not isinstance(params["vectors-b"], (pathlib.Path, str)):
        raise StyxValidationError(f'`vectors-b` has the wrong type: Received `{type(params.get("vectors-b", None))}` expected `InputPathType`')
    if params.get("operation", None) is None:
        raise StyxValidationError("`operation` must not be None")
    if not isinstance(params["operation"], str):
        raise StyxValidationError(f'`operation` has the wrong type: Received `{type(params.get("operation", None))}` expected `str`')
    if params.get("metric-out", None) is None:
        raise StyxValidationError("`metric-out` must not be None")
    if not isinstance(params["metric-out"], str):
        raise StyxValidationError(f'`metric-out` has the wrong type: Received `{type(params.get("metric-out", None))}` expected `str`')
    if params.get("magnitude", False) is None:
        raise StyxValidationError("`magnitude` must not be None")
    if not isinstance(params["magnitude"], bool):
        raise StyxValidationError(f'`magnitude` has the wrong type: Received `{type(params.get("magnitude", False))}` expected `bool`')
    if params.get("normalize-output", False) is None:
        raise StyxValidationError("`normalize-output` must not be None")
    if not isinstance(params["normalize-output"], bool):
        raise StyxValidationError(f'`normalize-output` has the wrong type: Received `{type(params.get("normalize-output", False))}` expected `bool`')
    if params.get("normalize-b", False) is None:
        raise StyxValidationError("`normalize-b` must not be None")
    if not isinstance(params["normalize-b"], bool):
        raise StyxValidationError(f'`normalize-b` has the wrong type: Received `{type(params.get("normalize-b", False))}` expected `bool`')
    if params.get("normalize-a", False) is None:
        raise StyxValidationError("`normalize-a` must not be None")
    if not isinstance(params["normalize-a"], bool):
        raise StyxValidationError(f'`normalize-a` has the wrong type: Received `{type(params.get("normalize-a", False))}` expected `bool`')


def metric_vector_operation_cargs(
    params: MetricVectorOperationParamsDict,
    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",
        "-metric-vector-operation"
    ])
    cargs.append(execution.input_file(params.get("vectors-a", None)))
    cargs.append(execution.input_file(params.get("vectors-b", None)))
    cargs.append(params.get("operation", None))
    cargs.append(params.get("metric-out", None))
    if params.get("magnitude", False):
        cargs.append("-magnitude")
    if params.get("normalize-output", False):
        cargs.append("-normalize-output")
    if params.get("normalize-b", False):
        cargs.append("-normalize-b")
    if params.get("normalize-a", False):
        cargs.append("-normalize-a")
    return cargs


def metric_vector_operation_outputs(
    params: MetricVectorOperationParamsDict,
    execution: Execution,
) -> MetricVectorOperationOutputs:
    """
    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 = MetricVectorOperationOutputs(
        root=execution.output_file("."),
        metric_out=execution.output_file(params.get("metric-out", None)),
    )
    return ret


def metric_vector_operation_execute(
    params: MetricVectorOperationParamsDict,
    runner: Runner | None = None,
) -> MetricVectorOperationOutputs:
    """
    DO A VECTOR OPERATION ON METRIC FILES.
    
    Does a vector operation on two metric files (that must have a multiple of 3
    columns). Either of the inputs may have multiple vectors (more than 3
    columns), but not both (at least one must have exactly 3 columns). The
    -magnitude and -normalize-output options may not be specified together, or
    with an operation that returns a scalar (dot product). The <operation>
    parameter must be one of the following:
    
    DOT
    CROSS
    ADD
    SUBTRACT.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `MetricVectorOperationOutputs`).
    """
    metric_vector_operation_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(METRIC_VECTOR_OPERATION_METADATA)
    params = execution.params(params)
    cargs = metric_vector_operation_cargs(params, execution)
    ret = metric_vector_operation_outputs(params, execution)
    execution.run(cargs)
    return ret


def metric_vector_operation(
    vectors_a: InputPathType,
    vectors_b: InputPathType,
    operation: str,
    metric_out: str,
    magnitude: bool = False,
    normalize_output: bool = False,
    normalize_b: bool = False,
    normalize_a: bool = False,
    runner: Runner | None = None,
) -> MetricVectorOperationOutputs:
    """
    DO A VECTOR OPERATION ON METRIC FILES.
    
    Does a vector operation on two metric files (that must have a multiple of 3
    columns). Either of the inputs may have multiple vectors (more than 3
    columns), but not both (at least one must have exactly 3 columns). The
    -magnitude and -normalize-output options may not be specified together, or
    with an operation that returns a scalar (dot product). The <operation>
    parameter must be one of the following:
    
    DOT
    CROSS
    ADD
    SUBTRACT.
    
    Args:
        vectors_a: first vector input file.
        vectors_b: second vector input file.
        operation: what vector operation to do.
        metric_out: the output file.
        magnitude: output the magnitude of the result (not valid for dot\
            product).
        normalize_output: normalize output vectors (not valid for dot product).
        normalize_b: normalize vectors of second input.
        normalize_a: normalize vectors of first input.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `MetricVectorOperationOutputs`).
    """
    params = metric_vector_operation_params(
        vectors_a=vectors_a,
        vectors_b=vectors_b,
        operation=operation,
        metric_out=metric_out,
        magnitude=magnitude,
        normalize_output=normalize_output,
        normalize_b=normalize_b,
        normalize_a=normalize_a,
    )
    return metric_vector_operation_execute(params, runner)


__all__ = [
    "METRIC_VECTOR_OPERATION_METADATA",
    "MetricVectorOperationOutputs",
    "MetricVectorOperationParamsDict",
    "MetricVectorOperationParamsDictTagged",
    "metric_vector_operation",
    "metric_vector_operation_execute",
    "metric_vector_operation_params",
]
