#!/bin/sh -eu
# ###########################################################################
#             Thomas Dreibholz's R Simulation Scripts Collection
#                  Copyright (C) 2005-2025 Thomas Dreibholz
#
#               Author: Thomas Dreibholz, thomas.dreibholz@gmail.com
# ###########################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http:/www.gnu.org/licenses/>.
#
# Contact: thomas.dreibholz@gmail.com

# ====== Check parameters ===================================================
if [ $# -lt 3 ] ; then
   echo >&2 "Usage: $0 [Simulation Directory] [Run Directory] [Run Number] {Pool Handle} {PU Misc Options}"
   echo >&2 "Example: $0   test1 test1/Simulations/Set-1234 1   ScriptingPool \"-cspserver=127.0.0.1\""
   exit 1
fi

SIMULATION_DIRECTORY="$(pwd)/$1"   # e.g.: `pwd`/test1
RUN_DIRECTORY=$2                   # e.g.: test1/Simulations/Set-1234
RUN_NUMBER=$3                      # e.g.: 1
POOLHANDLE=""
PU_MISCOPT=""
if [ $# -ge 4 ] ; then
   POOLHANDLE="$4"                 # e.g.: ScriptingPool
fi
if [ $# -ge 5 ] ; then
   PU_MISCOPT="$5"                 # e.g.: "-cspserver=... ..."
fi


RUN_PREFIX="run$RUN_NUMBER"
STATUS_FILE="$RUN_PREFIX-status.txt"
INI_FILE="$RUN_PREFIX-parameters.ini"
if [ -e "scenario$RUN_NUMBER.xml" ] ; then
   XML_FILE="scenario$RUN_NUMBER.xml"
else
   XML_FILE=""
fi

# ====== Check whether run still has to be performed ========================
# shellcheck disable=SC3013
if [ "$RUN_DIRECTORY/$INI_FILE" -ot "$RUN_DIRECTORY/$STATUS_FILE" ] || \
   [ -e "$RUN_DIRECTORY/$STATUS_FILE" ] ; then
   exit 0   # Run has already been processed
fi


echo "Performing run $RUN_PREFIX ..."

# ====== Perform run locally ================================================
if [ "$POOLHANDLE" = "" ] ; then

   # ====== Clone environment ===============================================
   RESULT=0
   RUN_ENVIRONMENT="$RUN_PREFIX-Environment"
   VECTOR_FILE="$RUN_PREFIX-vectors.vec"
   SCALAR_FILE="$RUN_PREFIX-scalars.sca"
   OUTPUT_FILE="$RUN_PREFIX-output.txt"

   echo "+ $(date) Cloning environment ..."
   if [ "$RUN_DIRECTORY" != "" ] && [ "$RUN_ENVIRONMENT" != "" ] ; then
      # shellcheck disable=SC2115
      rm -rf "$RUN_DIRECTORY/$RUN_ENVIRONMENT"
   fi
   mkdir "$RUN_DIRECTORY/$RUN_ENVIRONMENT"
   find "$SIMULATION_DIRECTORY/Environment" -type d -printf "%P\n" | xargs -I{} mkdir "$RUN_DIRECTORY/$RUN_ENVIRONMENT/{}"
   find "$SIMULATION_DIRECTORY/Environment" -type f -printf "%P\n" | xargs -I{} ln "$SIMULATION_DIRECTORY/Environment/{}" "$RUN_DIRECTORY/$RUN_ENVIRONMENT/{}"

   # %%%%%%%%%%%% Same code in perform-run and ssrun %%%%%%%%%%%%%%%%%%%%%%%%

   # ====== Get configuration ===============================================
   echo "+ $(date) Loading configuration (in $SIMULATION_DIRECTORY/Environment) ..."
   CONFIG_STAGES="$(ls "$SIMULATION_DIRECTORY"/Environment/simulation.config-stage?)"
   echo "   - Running configuration stages:"
   for stage in $CONFIG_STAGES ; do
      echo "      o Using $stage ..."
      # shellcheck disable=SC1090
      . "$stage"
   done

   echo "   - Run directory: $RUN_DIRECTORY"
   echo "   - Environment:   $RUN_DIRECTORY/$RUN_ENVIRONMENT"
   echo "      o Simulation base directory: $SIMULATION_BASEDIR"
   echo "      o Simulation libraries:      $SIMULATION_LIBS"
   echo "      o Simulation NED files:      $SIMULATION_NEDS"
   echo "      o Simulation program:        $SIMULATION_PROGRAM"
   nedArgs=""
   for n in $SIMULATION_NEDS ; do
      if [ "$nedArgs" = "" ] ; then
         nedArgs="$n"
      else
         nedArgs="$nedArgs:$n"
      fi
   done

   SIMULATION_ARGS="-u Cmdenv -f $INI_FILE -n $nedArgs"
   echo "      o Simulation arguments:      $SIMULATION_ARGS"


   # ====== Execute binary ==================================================
   echo "+ $(date) Executing simulation run ..."
   if [ ! -e "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR/$INI_FILE" ] ; then
      ln "$RUN_DIRECTORY/$INI_FILE" "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR/$INI_FILE"
   fi
   if [ "$XML_FILE" != "" ] ; then
      if [ ! -e "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR/$XML_FILE" ] ; then
         ln "$RUN_DIRECTORY/$XML_FILE" "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR/$XML_FILE"
      fi
   fi
   if [ ! -e "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR/$SIMULATION_PROGRAM" ] ; then
      ln "$SIMULATION_DIRECTORY/Environment/$SIMULATION_PROGRAM" "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR/$SIMULATION_PROGRAM"
   fi
   if [ ! -e "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR/$SIMULATION_LIBS" ] ; then
      ln -s "$SIMULATION_DIRECTORY/Environment/$SIMULATION_LIBS" "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR/$SIMULATION_LIBS"
   fi

   workDirectory="$(pwd)"

   cd "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR"
   startTime="$(date)"
   rm -f "$RUN_DIRECTORY/$SCALAR_FILE.bz2" "$RUN_DIRECTORY/$VECTOR_FILE.bz2" "$RUN_DIRECTORY/$OUTPUT_FILE.bz2"
   echo "   -> $SIMULATION_LIBS/ld-loader.so --library-path $SIMULATION_LIBS ./$SIMULATION_PROGRAM $SIMULATION_ARGS"
   chmod 700 "./$SIMULATION_PROGRAM"
   # shellcheck disable=SC2086
   "$SIMULATION_LIBS/ld-loader.so" --library-path "$SIMULATION_LIBS" "./$SIMULATION_PROGRAM" $SIMULATION_ARGS >"$OUTPUT_FILE" 2>&1
   find . \( -name "$OUTPUT_FILE" -or -name "$VECTOR_FILE" -or -name "$SCALAR_FILE" \) -print0 | xargs -0 -r bzip2 -f
   endTime="$(date)"
   ( echo "Start: $startTime" && echo "End:   $endTime" ) >"$STATUS_FILE"

   cd "$workDirectory"

   # %%%%%%%%%%%% Same code in perform-run and ssrun %%%%%%%%%%%%%%%%%%%%%%%%


   # ====== Save results and clean up =======================================
   echo "+ $(date) Cleaning up ..."
   find "$RUN_DIRECTORY/$RUN_ENVIRONMENT/$SIMULATION_BASEDIR" \( -maxdepth 1 -type f -name "*.bz2" -or -name "*.txt" \) -print0 | xargs -0 -r -I{} mv {} "$RUN_DIRECTORY"
   if [ "$RUN_DIRECTORY" != "" ] && [ "$RUN_ENVIRONMENT" != "" ] ; then
      # shellcheck disable=SC2115
      rm -rf "$RUN_DIRECTORY/$RUN_ENVIRONMENT"
   fi


   # ====== If run has failed: print output for debugging ===================
   if [ $RESULT -ne 0 ] ; then
      echo ""
      echo "----- SIMULATION RUN FAILED -----"
      echo ""

      echo "#########################################################"
      grep "^<\!> Error " "$RUN_DIRECTORY/$OUTPUT_FILE"
      echo "#########################################################"
      echo ""

      echo "INI file:      $RUN_DIRECTORY/$INI_FILE"
      echo "Scenario file: $RUN_DIRECTORY/$XML_FILE"
      echo "Output file:   $RUN_DIRECTORY/$OUTPUT_FILE"
      echo "----- SIMULATION RUN FAILED -----"
   fi

   exit $RESULT


# ====== Distribute run into pool ===========================================
else
   ./ssdistribute "$1" "$2" "$INI_FILE" "$POOLHANDLE" "$PU_MISCOPT" "$XML_FILE"
fi
