#! /usr/bin/env python

import os
import sys
import pathlib
import inspect

import waves

# Accept command line options with fall back default values
AddOption(
    "--build-dir",
    dest="variant_dir_base",
    default="build",
    nargs=1,
    type="string",
    action="store",
    metavar="DIR",
    help="SCons build (variant) root directory. Relative or absolute path. (default: '%default')"
)
AddOption(
    "--ignore-documentation",
    dest="ignore_documentation",
    default=False,
    action="store_true",
    help="Boolean to ignore the documentation build, e.g. during Conda package build and testing. Unaffected by the " \
         "'--unconditional-build' option. (default: '%default')"
)
AddOption(
    "--solve-cpus",
    dest="solve_cpus",
    default=1,
    nargs=1,
    type="int",
    action="store",
    metavar="N",
    help="Run the Abaqus Solve task using N CPUs. (default: '%default')"
)

# Inherit user's full environment and set project options
env = Environment(ENV=os.environ.copy(),
                  variant_dir_base=GetOption("variant_dir_base"),
                  ignore_documentation=GetOption("ignore_documentation"),
                  solve_cpus=GetOption("solve_cpus"),
                  TARFLAGS="-c -j",
                  TARSUFFIX=".tar.bz2")

# 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["sphinx_build"] = waves.scons_extensions.add_program(["sphinx-build"], env)
env["abaqus"] = waves.scons_extensions.add_program(["/apps/abaqus/Commands/abq2023", "abq2023"], env)

# Set project internal variables and variable substitution dictionaries
project_configuration = pathlib.Path(inspect.getfile(lambda: None))
project_dir = project_configuration.parent
project_name = project_dir.name
author_list = ["Kyle Brindley",
               "Prabhu S. Khalsa",
               "Thomas Roberts",
               "Sergio Cordova",
               "Matthew Fister",
               "Scott Ouellette"]
author_latex = r" \and ".join(author_list)
documentation_source_dir = pathlib.Path("docs")
eabm_package_dir = "eabm_package"
project_variables = {
    "project_configuration": str(project_configuration),
    "project_dir": str(project_dir),
    "project_name": project_name,
    "version": "0.1.0",
    "author_list": author_list,
    "author_latex": author_latex,
    "documentation_abspath": str(project_dir / documentation_source_dir),
    "eabm_package_abspath": str(project_dir / eabm_package_dir),
    "datacheck_alias": "datacheck"
}
for key, value in project_variables.items():
    env[key] = value

# Make the EABM package importable for: (1) SConscript files and (2) Python and Abaqus Python environments
sys.path.insert(0, str(project_dir))
env.PrependENVPath("PYTHONPATH", str(project_dir))

# Build path object for extension and re-use
variant_dir_base = pathlib.Path(env["variant_dir_base"])

# Add WAVES builders and scanners
env.Append(BUILDERS={
    "AbaqusJournal": waves.scons_extensions.abaqus_journal(program=env["abaqus"]),
    "AbaqusSolver": waves.scons_extensions.abaqus_solver(program=env["abaqus"]),
    "AbaqusExtract": waves.scons_extensions.abaqus_extract(program=env["abaqus"]),
    "PythonScript": waves.scons_extensions.python_script(),
    "CondaEnvironment": waves.scons_extensions.conda_environment()
})
env.Append(SCANNERS=waves.scons_extensions.sphinx_scanner())

# Dump the Conda environment as documentation of as-built target environment
environment_target = env.CondaEnvironment(
    target=["environment.yaml"],
    source=[])
env.AlwaysBuild(environment_target)
Default(environment_target)

# Add documentation target(s)
if not env["ignore_documentation"]:
    # Project documentation
    build_dir = variant_dir_base / documentation_source_dir
    docs_aliases = SConscript(str(documentation_source_dir / "SConscript"), variant_dir=str(build_dir), exports=["env", "project_variables"])

    # Analysis report
    report_dir = pathlib.Path("report")
    build_dir = variant_dir_base / report_dir
    SConscript(str(report_dir / "SConscript"),
               variant_dir=str(build_dir),
               exports=["env", "project_variables"],
               duplicate=True)
else:
    print(f"The 'ignore_documentation' option was set to 'True'. Skipping documentation SConscript file(s)")
    docs_aliases = []

# Add simulation targets
workflow_configurations = [
    "nominal",
    "mesh_convergence"
]
for workflow in workflow_configurations:
    build_dir = variant_dir_base / workflow
    SConscript(workflow, variant_dir=build_dir, exports="env", duplicate=False)

# Add default target list to help message
# Add aliases to help message so users know what build target options are available
# This must come *after* all expected Alias definitions and SConscript files.
waves.scons_extensions.project_help_message()
