#! /usr/bin/env python

import os
import pathlib

import waves

# Add build directory CLI arg
AddOption(
    "--build-dir",
    dest="build_dir",
    default="build",
    nargs=1,
    type="string",
    action="store",
    metavar="DIR",
    help="SCons build (variant) root directory. Relative or absolute path. (default: '%default')",
)
AddOption(
    "--unconditional-build",
    dest="unconditional_build",
    default=False,
    action="store_true",
    help="Boolean to force building of conditionally ignored targets. (default: '%default')",
)
# Python optparse appends to the default list instead of overriding. Must implement default/override ourselves.
# documentation-marker-default-abaqus-commands-start
default_abaqus_commands = [
    "/apps/abaqus/Commands/abq2024",
    "/usr/projects/ea/abaqus/Commands/abq2024",
    "abq2024",
    "abaqus",
]
# documentation-marker-default-abaqus-commands-end
AddOption(
    "--abaqus-command",
    dest="abaqus_command",
    nargs=1,
    type="string",
    action="append",
    metavar="COMMAND",
    help=f"Override for the Abaqus command. Repeat to specify more than one (default: {default_abaqus_commands})",
)

# Inherit user's full environment
env = waves.scons_extensions.WAVESEnvironment(
    ENV=os.environ.copy(),
    build_dir=pathlib.Path(GetOption("build_dir")),
    unconditional_build=GetOption("unconditional_build"),
    abaqus_commands=GetOption("abaqus_command"),
)
env["parameter_study_directory"] = env["build_dir"] / "parameter_studies"

# Always copy (no sym-links) when duplicating
env.SetOption("duplicate", "copy")

# Empty defaults list to avoid building all simulation targets by default
env.Default()

# Find required programs for conditional target ignoring and absolute path for use in target actions
env["ABAQUS_PROGRAM"] = env.AddProgram(
    env["abaqus_commands"] if env["abaqus_commands"] is not None else default_abaqus_commands
)

# Add WAVES builders
env.Append(
    BUILDERS={
        "AbaqusExtract": waves.scons_extensions.abaqus_extract(program=env["ABAQUS_PROGRAM"]),
    }
)

# Abaqus input file implicit dependency scanner
env.Append(SCANNERS=waves.scons_extensions.abaqus_input_scanner())

# Define parameter studies
nominal_parameters = {
    "width": 1.0,
    "height": 1.0,
    "global_seed": 1.0,
    "displacement": -0.01,
}
mesh_convergence_parameter_study_file = env["parameter_study_directory"] / "mesh_convergence.h5"
mesh_convergence_parameter_generator = waves.parameter_generators.CartesianProduct(
    {
        "width": [1.0],
        "height": [1.0],
        "global_seed": [1.0, 0.5, 0.25, 0.125],
        "displacement": [-0.01],
    },
    output_file=mesh_convergence_parameter_study_file,
    previous_parameter_study=mesh_convergence_parameter_study_file,
)
mesh_convergence_parameter_generator.write()

# Add workflow(s)
workflow_configurations = [
    ("nominal", nominal_parameters),
    ("mesh_convergence", mesh_convergence_parameter_generator),
]
for study_name, study_definition in workflow_configurations:
    env.ParameterStudySConscript(
        "SConscript",
        variant_dir=env["build_dir"] / study_name,
        exports={"env": env, "alias": study_name},
        study=study_definition,
        subdirectories=True,
        duplicate=True,
    )

# List all aliases in help message.
# This must come *after* all expected Alias definitions and SConscript files.
env.ProjectHelp()
