Bootstrap: docker
From: ubuntu:18.04

%labels
    Author="GRADES"
    Institution="Synchrotron SOLEIL"
    Version="3.5.10"
    System="ubuntu:18.04"
    Packages="foxtrot"
    Entrypoint="/opt/foxtrot/foxtrot.sh"
    Description="Foxtrot 3.5.10 with Java 8 and Python 2.7 (Apptainer)"

%environment
    export LC_ALL=C
    export LANG=C

    export FOXTROT_PATH=/opt/foxtrot
    export FOXTROT_CONFIG_PATH=/opt/foxtrot/config

    # Nom du fichier de configuration
    export FOXTROT_CONFIG_FILENAME=defaultData.properties

    export PATH=$FOXTROT_PATH:$PATH
    export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

    # Chemin configurable par l'utilisateur (par défaut dans le HOME)
    export FOXTROT_USER_CONFIG_PATH=${FOXTROT_USER_CONFIG_PATH:-$HOME}

%post
    set -e

    FOXTROT_VERSION=3.5.10
    FOXTROT_ZIP_FILENAME="foxtrot-${FOXTROT_VERSION}-users.zip"
    FOXTROT_BASE_URL="https://www.synchrotron-soleil.fr/sites/default/files"
    FOXTROT_ZIP_URL="${FOXTROT_BASE_URL}/${FOXTROT_ZIP_FILENAME}"

    FOXTROT_PATH=/opt/foxtrot
    FOXTROT_CONFIG_PATH=/opt/foxtrot/config
    FOXTROT_CONFIG_FILENAME=defaultData.properties

    mkdir -p ${FOXTROT_PATH}
    mkdir -p ${FOXTROT_CONFIG_PATH}
        
    echo "Installation des dépendances système..."
    apt-get update && apt-get install -y \
        dbus \
        openjdk-8-jre \
        python2.7 \
        python-pip \
        python-h5py \
        unzip \
        wget \
        ca-certificates \
        procps \
        && rm -rf /var/lib/apt/lists/*

    # Fix éventuel pour liens Foxtrot
    ln -s /opt/foxtrot /opt/Foxtrot || true

    dbus-uuidgen > /etc/machine-id

    echo "Mise à jour de pip (version compatible avec Python 2)..."
    pip install --upgrade "pip<21"

    echo "Installation du module tifffile..."
    pip install tifffile==2019.7.26

    echo "Vérification de l'URL..."
    if ! wget --spider -q "${FOXTROT_ZIP_URL}"; then
        echo "ERREUR: URL invalide ou inaccessible: ${FOXTROT_ZIP_URL}"
        exit 1
    fi

    echo "Téléchargement..."
    wget -O /tmp/${FOXTROT_ZIP_FILENAME} "${FOXTROT_ZIP_URL}" || {
        echo "ERREUR téléchargement"
        exit 1
    }

    echo "Détection du dossier dans l'archive..."
    TOP_DIR=$(unzip -qql /tmp/${FOXTROT_ZIP_FILENAME} | awk '{print $4}' | cut -d/ -f1 | sort -u | head -n1)

    if [ -z "$TOP_DIR" ]; then
        echo "ERREUR: impossible de détecter le dossier racine dans le zip"
        exit 1
    fi

    echo "Dossier détecté: $TOP_DIR"

    echo "Décompression..."
    unzip /tmp/${FOXTROT_ZIP_FILENAME} -d /tmp

    echo "Installation dans ${FOXTROT_PATH}..."
    cp -r /tmp/${TOP_DIR}/. ${FOXTROT_PATH}/
    rm -rf /tmp/${TOP_DIR}

    echo "Correction des permissions des scripts..."
    chmod +x ${FOXTROT_PATH}/foxtrot.sh
    chmod +x ${FOXTROT_PATH}/python/extractor.sh
    find ${FOXTROT_PATH}/resources/tools -name "*.sh" -exec chmod +x {} \;

    # =========================
    # PATCH foxtrot.sh
    # =========================

    # JVM CONFIGURATION
    # -----------------

    # Mémoire heap initiale (allocation de départ de la JVM)
    # -> évite des redimensionnements trop fréquents
    JAVA_XMS=2g

    # Mémoire heap maximale (limite principale de la JVM)
    # -> NE DOIT PAS dépasser ~70-80% de la RAM du conteneur
    JAVA_XMX=8g

    # Limite de la Metaspace (stockage des classes Java)
    # -> évite une croissance infinie si fuite de classloaders
    JAVA_MAX_METASPACE=512m

    # Limite mémoire "directe" (off-heap)
    # -> CRITIQUE pour bibliothèques natives (ex: HDF5, NIO)
    # -> souvent responsable de "fuites mémoire invisibles" au heap
    JAVA_MAX_DIRECT=1g

    # OPTIONS JVM GLOBALES
    # --------------------

    # Options expérimentales (Java 8)
    # -> nécessaire pour activer le support des cgroups
    # Option: -XX:+UnlockExperimentalVMOptions

    # Support des conteneurs (Java 8)
    # -> permet à la JVM de respecter la RAM du conteneur
    # -> sinon elle voit la RAM de l’hôte (dangereux)
    # Option: -XX:+UseCGroupMemoryLimitForHeap

    # Dump mémoire en cas d'erreur
    # -> génère un fichier .hprof pour analyser les fuites
    # Option: -XX:+HeapDumpOnOutOfMemoryError
    # Option -XX:HeapDumpPath=/tmp/foxtrot_heapdump.hprof

    JAVA_TOOL_OPTIONS="-Xms${JAVA_XMS} -Xmx${JAVA_XMX} -XX:MaxMetaspaceSize=${JAVA_MAX_METASPACE} -XX:MaxDirectMemorySize=${JAVA_MAX_DIRECT} -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/foxtrot_heapdump.hprof"
    echo ""
    echo "JAVA_TOOL_OPTIONS:"
    echo $JAVA_TOOL_OPTIONS

    echo "Patch JVM options dans foxtrot.sh..."
    sed -i "s|JAVA_OPTIONS=.*|JAVA_OPTIONS=\"$JAVA_TOOL_OPTIONS -Dcom.sun.management.jmxremote=true\"|" "${FOXTROT_PATH}/foxtrot.sh"

    echo "Vérification de JAVA_OPTIONS dans le fichier ${FOXTROT_PATH}/foxtrot.sh :" 
    grep 'JAVA_OPTIONS' ${FOXTROT_PATH}/foxtrot.sh
    
    # =========================
    # FIN DU PATCH
    # =========================

    echo "Java version:"
    java -version

    echo "Création du fichier de configuration par défaut..."
    cat <<EOF > ${FOXTROT_CONFIG_PATH}/${FOXTROT_CONFIG_FILENAME}
Beamline;swing;false
X0;0.0;false
Z0;0.0;false
PixelSize;41.7;false
XBin;1;false
ZBin;1;false
EncoderDelta;0.0;false
Delta0;0.0;false
Gamma0;0.0;false
DetectorBias;200;false
DetectorGain;0.28;false
DetectorBasedUncertainty;0.0;false
WaveLength;1.0;false
ExposureTime;1.0;false
ShutterCloseDelay;0.0;false
Distance;1.0;false
EOF


%runscript

    TARGET_DIR="${FOXTROT_USER_CONFIG_PATH:-$HOME}"
    TARGET_FILE="${TARGET_DIR}/${FOXTROT_CONFIG_FILENAME}"

    if [ ! -f "$TARGET_FILE" ]; then
        echo "Création du fichier de config dans: $TARGET_FILE"
        mkdir -p "$TARGET_DIR"
        cp -n ${FOXTROT_CONFIG_PATH}/${FOXTROT_CONFIG_FILENAME} "$TARGET_FILE"
    fi

    exec ${FOXTROT_PATH}/foxtrot.sh "$@"
