#! /usr/bin/env python
"""Configure the WAVES Gmsh tutorial."""

import inspect
import os
import pathlib
import sys

import waves

# Add build directory CLI arg
AddOption(
    "--build-dir",
    dest="build_directory",
    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')",
)

# Inherit user's full environment
project_configuration = pathlib.Path(inspect.getfile(lambda: None))
project_directory = project_configuration.parent
build_directory = pathlib.Path(GetOption("build_directory"))
env = waves.scons_extensions.WAVESEnvironment(
    ENV=os.environ.copy(),
    project_directory=project_directory,
    unconditional_build=GetOption("unconditional_build"),
)
env["parameter_study_directory"] = build_directory / "parameter_studies"

# Make the project package importable for: (1) SConscript files
sys.path.insert(0, str(project_directory))

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

# Always print failed task *.stdout files
env.PrintBuildFailures(print_stdout=True)

# 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["CCX_PROGRAM"] = env.AddProgram(["ccx"])
env["ccx2paraview"] = env.AddProgram(["ccx2paraview"])

# Abaqus input file implicit dependency scanner
# Works for CalculiX because CalculiX uses the Abaqus include keyword semantics and input file extension
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=build_directory / 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()
