#!/bin/bash
# Instrumented Allrun — writes timing to foam_timing.json on completion.
set -e
cd "${0%/*}" || exit
. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions

TIMING_FILE="${TIMING_FILE:-foam_timing.json}"

ts() { date +%s%N | awk '{printf "%.6f", $1/1e9}'; }
# bc omits leading zero for 0 < x < 1 (e.g. ".5" not "0.5") — invalid JSON.
# Fix: prepend "0" when output starts with ".".
bc_dur() { echo "$(ts) - $1" | bc | awk '{if ($0 ~ /^\./) print "0" $0; else print $0}'; }

t_start=$(ts)

function getValue() {
    grep ^$1 $2 | awk '{$1=$1;print}' | cut -d' ' -f2 | tr -d ';'
}

# ── SERIAL SETUP ──────────────────────────────────────────────────────────────
mkdir -p constant/triSurface pre

t0=$(ts)
runApplication surfaceConvert input/buildings.obj constant/triSurface/buildings.stl
if [ -f input/forest.obj ]; then
    awk -f awk/forestshell.awk input/forest.obj > constant/triSurface/forest.stl
    cp constant/fvOptions.forest constant/fvOptions.tree
    cp system/forestGeometry system/forestRegion pre/
else
    # parallel snappyHexMesh aborts on a missing #includeIfPresent file
    : > pre/forestGeometry
    : > pre/forestRegion
fi
t_convert=$(bc_dur $t0)

cellMax=$(getValue cellMax uap_simple.cfg)
height=$(getValue minHeight uap_simple.cfg)

awk -f awk/genground.awk       -v cs=$cellMax -v xg=4 constant/triSurface/buildings.stl > constant/triSurface/ground.stl
awk -f awk/genrefinement.awk   -v cs=$cellMax -v xg=4 constant/triSurface/buildings.stl > constant/triSurface/central_box_constraint.stl
awk -f awk/stlminmax.awk       constant/triSurface/buildings.stl > pre/bbox_buildings
awk -f awk/stlminmax.awk       constant/triSurface/ground.stl   > pre/bbox_ground
awk -f awk/blockmeshparams.awk -v cs=$cellMax -v vh=$height constant/triSurface/ground.stl > pre/blockmeshparams
awk -f awk/locationInMesh.awk  -v cs=$cellMax -v vh=$height constant/triSurface/ground.stl > pre/locationInMesh
awk -f awk/boxCentre.awk       -v cs=$cellMax -v vh=$height constant/triSurface/ground.stl > pre/boxCentre

t0=$(ts)
runApplication surfaceFeatureExtract
t_feature=$(bc_dur $t0)

t0=$(ts)
runApplication blockMesh
runApplication -s block checkMesh
t_blockmesh=$(bc_dur $t0)

t0=$(ts)
runApplication decomposePar
t_decompose=$(bc_dur $t0)

t_setup=$(echo "$t_convert + $t_feature + $t_blockmesh + $t_decompose" | bc | awk '{if ($0 ~ /^\./) print "0" $0; else print $0}')

# ── PARALLEL MESH ─────────────────────────────────────────────────────────────
t0=$(ts)
runParallel snappyHexMesh -overwrite
runParallel -s snappy checkMesh
runParallel renumberMesh -overwrite
if [ -f constant/triSurface/forest.stl ]; then
    runParallel topoSet
fi
t_mesh=$(bc_dur $t0)

# extract cell count from snappy checkMesh log
NCELLS=$(grep -m1 "cells:" log.checkMesh.snappy 2>/dev/null | awk '{print $NF}')
[ -z "$NCELLS" ] && NCELLS=null

# ── PARALLEL SIMULATION ───────────────────────────────────────────────────────
restore0Dir -processor
cp uap*.cfg processor*

t0=$(ts)
runParallel potentialFoam -writephi
t_potential=$(bc_dur $t0)

t0=$(ts)
runParallel simpleFoam
t_sim=$(bc_dur $t0)

t_total=$(bc_dur $t_start)

# ── WRITE TIMING JSON ─────────────────────────────────────────────────────────
NCORES=$(awk '/nCores/{gsub(/;/,""); print $2; exit}' uap_simple.cfg 2>/dev/null || echo "1")
[ -z "$NCORES" ] && NCORES=1

cat > "$TIMING_FILE" <<EOF
{
  "T_setup_s":    $t_setup,
  "T_convert_s":  $t_convert,
  "T_feature_s":  $t_feature,
  "T_blockmesh_s": $t_blockmesh,
  "T_decompose_s": $t_decompose,
  "T_mesh_s":     $t_mesh,
  "T_potential_s": $t_potential,
  "T_sim_s":      $t_sim,
  "T_foam_total_s": $t_total,
  "n_cells":      $NCELLS,
  "n_cores":      $NCORES,
  "workdir":      "$(pwd)"
}
EOF

echo "Timing written to $TIMING_FILE"
