#! /usr/bin/env python

import os
import pathlib


# Accept command line options with fall back default values
AddOption(
    "--build-dir",
    dest="variant_dir_base",
    default="build_scons_multiactiontask",
    nargs=1,
    type="string",
    action="store",
    metavar="DIR",
    help="SCons build (variant) root directory. Relative or absolute path. (default: '%default')"
)

# Inherit user's full environment
env = Environment(
    ENV=os.environ.copy(),
    variant_dir_base=GetOption("variant_dir_base"),
)

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

# Set project-wide paths with os-agnostic path separators
project_dir = pathlib.Path(Dir('.').abspath)
abaqus_source_dir = 'eabm_package/abaqus'

# Make the EABM package importable for Python and Abaqus Python environments
env.PrependENVPath("PYTHONPATH", str(project_dir))

# Separate target output from source files
variant_dir_base = pathlib.Path(env['variant_dir_base'])
VariantDir(variant_dir_base.name, '.', duplicate=False)

# Find required programs for conditional target ignoring and absolute path for use in target actions
conf = env.Configure()
env['abaqus'] = conf.CheckProg('/apps/abaqus/Commands/abq2023')
conf.Finish()
if env['abaqus']:
    env.PrependENVPath("PATH", str(pathlib.Path(env['abaqus']).parent))

# Write project builders for re-use in task definitions
abaqus_journal = Builder(
    action="cd ${TARGET.dir.abspath} && ${abaqus_program} cae -noGui ${SOURCE.abspath} " \
           "${abaqus_options} -- ${journal_options}")

abaqus_solver = Builder(
    action="cd ${TARGET.dir.abspath} && ${abaqus_program} -job ${job_name} -input ${SOURCE.filebase} " \
           "${abaqus_options} -interactive -ask_delete no")

# Add custom builders
env.Append(BUILDERS={
    'AbaqusJournal': abaqus_journal,
    'AbaqusSolver': abaqus_solver
})

# Collect the target nodes to build a concise alias for all targets
workflow = []

# Geometry, Partition, Mesh
workflow.extend(env.Command(
    target=[str(variant_dir_base / "rectangle_mesh.cae"), str(variant_dir_base / "rectangle_mesh.inp")],
    source=[str(project_dir / abaqus_source_dir / "rectangle_geometry.py"),
            str(project_dir / abaqus_source_dir / "rectangle_partition.py"),
            str(project_dir / abaqus_source_dir / "rectangle_mesh.py")],
    action=["cd ${TARGET.dir.abspath} && ${abaqus_program} cae -noGui ${SOURCE.dir.abspath}/rectangle_geometry.py " \
            "${abaqus_options} -- --output-file ${TARGET.filebase}",
            "cd ${TARGET.dir.abspath} && ${abaqus_program} cae -noGui ${SOURCE.dir.abspath}/rectangle_partition.py " \
            "${abaqus_options} -- --input-file ${TARGET.filebase} --output-file ${TARGET.filebase}",
            "cd ${TARGET.dir.abspath} && ${abaqus_program} cae -noGui ${SOURCE.dir.abspath}/rectangle_mesh.py " \
            "${abaqus_options} -- --input-file ${TARGET.filebase} --output-file ${TARGET.filebase}"],
    abaqus_program=env['abaqus']
))

# SolverPrep
abaqus_source_list = [
    project_dir / abaqus_source_dir / "rectangle_compression.inp",
    project_dir / abaqus_source_dir / "assembly.inp",
    project_dir / abaqus_source_dir / "boundary.inp",
    project_dir / abaqus_source_dir / "field_output.inp",
    project_dir / abaqus_source_dir / "materials.inp",
    project_dir / abaqus_source_dir / "parts.inp",
    project_dir / abaqus_source_dir / "history_output.inp"
]
for source_file in abaqus_source_list:
    copy_target = variant_dir_base / source_file.name
    workflow.extend(env.Command(
        target=str(copy_target),
        source=str(source_file),
        action=Copy('${TARGET}', '${SOURCE}')))

# Abaqus Solve
abaqus_options = '-double both'
solve_source_list = [str(variant_dir_base / source_file.name) for source_file in abaqus_source_list]
solve_source_list.append(str(variant_dir_base / "rectangle_mesh.inp"))

solve_targets = [
    str(variant_dir_base / "rectangle_compression.odb"),
    str(variant_dir_base / "rectangle_compression.dat"),
    str(variant_dir_base / "rectangle_compression.msg"),
    str(variant_dir_base / "rectangle_compression.com"),
    str(variant_dir_base / "rectangle_compression.prt"),
    str(variant_dir_base / "rectangle_compression.sta")
]

workflow.extend(env.AbaqusSolver(
    target=solve_targets,
    source=solve_source_list,
    abaqus_program=env['abaqus'],
    job_name="rectangle_compression",
    abaqus_options=abaqus_options))

# Collector alias named after the model simulation
env.Alias("rectangle", workflow)

if not env['abaqus']:
    print("Program 'abaqus' was not found in construction environment. Ignoring 'rectangle' target(s)")
    Ignore(['.', "rectangle"], workflow)
