# syntax=docker/dockerfile:1.4
# Dockerfile for base CORSIKA / sim_telarray build.
#
# Contains only CORSIKA (non-optimized / optimized) and sim_telarray
# Requires CORSIKA and sim_telarray source code tarballs (plus tarball for
# CORSIKA optimized build) to be in the same directory as this Dockerfile.

# Shared build arguments
ARG CORSIKA_VERSION="77550"
ARG CORSIKA_OPT_PATCH_VERSION="v1.1.0"
ARG BUILD_OPT="prod6-sc"
ARG EXTRA_DEF="-DMAXIMUM_TELESCOPES=128"
ARG HADRONIC_MODEL="qgs2"
ARG AVX_FLAG="avx2"
ARG BERNLOHR_VERSION="1.68"
ARG AUTOCONF_VERSION="2.71"

#
# hadolint global ignore=DL3013,DL3033,DL3041,SC1091
# - DL3013, DL3033: ignore warnings about installing non-specific versions with microdnf or yum)
# - SC1091: ignore warning about not being able to source the bashrc

FROM almalinux:9.5 AS patches_stage
ARG CORSIKA_VERSION
ARG CORSIKA_OPT_PATCH_VERSION

RUN yum update -y && yum install -y git && \
    yum clean all && \
    rm -rf /var/cache/yum/* /tmp/* /var/tmp/*

RUN --mount=type=secret,id=gitlab_token \
    git config --global advice.detachedHead false && \
    git clone --depth 1 --branch "${CORSIKA_OPT_PATCH_VERSION}" "https://oauth2:$(cat /run/secrets/gitlab_token)@gitlab.cta-observatory.org/cta-computing/dpps/simpipe/corsika-opt-patches.git" && \
    cp -rL corsika-opt-patches/build_opt/corsikaOptPatch-$CORSIKA_VERSION/ ./corsika-patches/ && \
    rm -rf corsika-opt-patches

FROM almalinux:9.5 AS build_image
ARG BUILD_OPT
ARG EXTRA_DEF
ARG HADRONIC_MODEL
ARG AVX_FLAG
ARG CORSIKA_VERSION
ARG BERNLOHR_VERSION
ARG CORSIKA_OPT_PATCH_VERSION
ARG AUTOCONF_VERSION

ENV GCC_PATH="/usr/bin/"

RUN yum update -y && yum install -y \
    gcc-fortran gsl-devel libgfortran \
    automake csh patch perl which bzip2 \
    wget make tar m4 && \
    yum clean all && \
    rm -rf /var/cache/yum/* /tmp/* /var/tmp/*

WORKDIR /tmp/
ADD autoconf.tar.gz /tmp/
# hadolint ignore=DL3003
RUN cd "autoconf-$AUTOCONF_VERSION" && \
    ./configure --prefix=/usr && \
    make && make install && \
    cd / && rm -rf /tmp/autoconf-*

WORKDIR /workdir/sim_telarray
ADD corsika_simtelarray.tar.gz .
COPY --from=patches_stage /corsika-patches ./corsika-$CORSIKA_VERSION/

RUN tar -zxf corsika-$CORSIKA_VERSION.tar.gz && \
    tar -zxf bernlohr-$BERNLOHR_VERSION.tar.gz -C corsika-$CORSIKA_VERSION/bernlohr && \
    rm -f examples-with-data.tar.gz sim_telarray_config.tar.gz \
    corsika_simtelarray.tar.gz  corsika-$CORSIKA_VERSION.tar.gz \
    bernlohr-$BERNLOHR_VERSION.tar.gz

# Apply patches for non-optimized / optimized CORSIKA
WORKDIR /workdir/sim_telarray/corsika-$CORSIKA_VERSION
RUN if [ "$CORSIKA_VERSION" = "77550" ]; then \
        patch -b -p0 src/corsika.F < "../corsika-77550.patch"; \
    fi && \
    if [ "$AVX_FLAG" = "no_opt" ]; then \
        ../corsika_build_script "$HADRONIC_MODEL" generic; \
    else \
        ./corsika_opt_patching.sh && \
        autoreconf && \
        ../corsika_build_script "$HADRONIC_MODEL" generic cerenkopt vlibm; \
    fi

# Build non-optimized / optimized CORSIKA
WORKDIR /workdir/sim_telarray
RUN make -C "corsika-$CORSIKA_VERSION" clean && rm -f ./*/*.a lib/*/*.a && \
    AVX_EXTRA_FLAG=$([ "$AVX_FLAG" = "avx512f" ] && echo "-ffp-contract=off" || echo "") && \
    AVX_EXTRA_FLAG="" && \
    CFLAGS="" && CXXFLAGS="" && FFLAGS="" && \
    if [ "$AVX_FLAG" = "no_opt" ]; then \
        CFLAGS="-g  -std=c99 -O3"; \
        CXXFLAGS="-g  -std=c99 -O3"; \
        FFLAGS="-g -ffixed-line-length-132 -fno-automatic -frecord-marker=4 -std=legacy -O3"; \
    else \
        CFLAGS="-g -DCERENKOPT -DVLIBM -std=c99 -O3 ${AVX_FLAG:+-m$AVX_FLAG} ${AVX_EXTRA_FLAG} -DVECTOR_SIZE=8 -DVECTOR_LENGTH=8"; \
        CXXFLAGS="-g -DCERENKOPT -DVLIBM -std=c99 -O3 ${AVX_FLAG:+-m$AVX_FLAG} ${AVX_EXTRA_FLAG} -DVECTOR_SIZE=8 -DVECTOR_LENGTH=8"; \
        FFLAGS="-g -ffixed-line-length-132 -fno-automatic -frecord-marker=4 -std=legacy -DCERENKOPT -DVLIBM -std=c99 -O3 ${AVX_FLAG:+-m$AVX_FLAG} ${AVX_EXTRA_FLAG} -DVECTOR_SIZE=8 -DVECTOR_LENGTH=8"; \
    fi && \
    make -C "corsika-$CORSIKA_VERSION" \
        CC="${GCC_PATH}/gcc -static" \
        CXX="${GCC_PATH}/g++ -static" \
        CPP="${GCC_PATH}/gcc -static -E" \
        F77="${GCC_PATH}/gfortran -L/lib64/" \
        CFLAGS="${CFLAGS}" \
        CXXFLAGS="${CXXFLAGS}" \
        FFLAGS="${FFLAGS}" \
        install

# Rename executable to 'corsika'
RUN mv -f "corsika-${CORSIKA_VERSION}/run/corsika${CORSIKA_VERSION}Linux_"* "corsika-${CORSIKA_VERSION}/run/corsika"
# Build sim_telarray (with and without debug options)
RUN touch corsika-$CORSIKA_VERSION.tar.gz && \
    # build with debug options; move binary to temporary location (to avoid being purged in next step)
    export NO_CORSIKA=1 EXTRA_DEFINES="${EXTRA_DEF} -DDEBUG_TRACE_99" && ./build_all $BUILD_OPT $HADRONIC_MODEL gsl && \
    mv /workdir/sim_telarray/sim_telarray/sim_telarray \
       /workdir/sim_telarray/sim_telarray/sim_telarray_debug_trace && \
    # build without debug options; move debug option binary back to sim_telarray/bin
    export NO_CORSIKA=1 EXTRA_DEFINES="${EXTRA_DEF}" && ./build_all $BUILD_OPT $HADRONIC_MODEL gsl && \
    mv /workdir/sim_telarray/sim_telarray/sim_telarray_debug_trace \
       /workdir/sim_telarray/sim_telarray/bin/sim_telarray_debug_trace

# CORSIKA source code is removed to follow
# the CORSIKA non-distribution policy.
RUN mv ./corsika-7*/run corsika-run && \
    rm -rf ./corsika-7[0-9]* && \
    find . -name "*.tar.gz" -delete && \
    find . -name "doc*" -type d -exec rm -rf "{}" + 2>/dev/null && \
    find . -name "*.o" -delete && \
    rm -rf /var/cache/yum/* /tmp/* /var/tmp/*

# Use QGSJet tables downloaded externally (overwrite any existing copies)
WORKDIR /workdir/sim_telarray/corsika-run
COPY qgsdat-II-04.bz2 .
COPY qgsdat-III.bz2 .
RUN if [ "$HADRONIC_MODEL" = "qgs3" ]; then \
        if [ -f qgsdat-III.bz2 ]; then \
            bzip2 -dq qgsdat-III.bz2; \
        fi; \
        rm -f -v qgsdat-II-04.bz2; \
    fi && \
    if [ "$HADRONIC_MODEL" = "qgs2" ]; then \
        if [ -f qgsdat-II-04.bz2 ]; then \
            bzip2 -dq qgsdat-II-04.bz2; \
        fi; \
        rm -f -v qgsdat-III.bz2; \
    fi

# Add a yml file in workdir with the build options
WORKDIR /workdir/sim_telarray
RUN echo "build_opt: $BUILD_OPT" > ./build_opts.yml && \
    echo "extra_def: $EXTRA_DEF" >> ./build_opts.yml && \
    echo "hadronic_model: $HADRONIC_MODEL" >> ./build_opts.yml && \
    echo "avx_flag: $AVX_FLAG" >> ./build_opts.yml && \
    echo "corsika_version: $CORSIKA_VERSION" >> ./build_opts.yml && \
    echo "corsika_opt_patch_version: $CORSIKA_OPT_PATCH_VERSION" >> ./build_opts.yml && \
    echo "bernlohr_version: $BERNLOHR_VERSION" >> ./build_opts.yml

# Final stage - minimal base image with CORSIKA and sim_telarray
FROM almalinux:9.5-minimal
COPY --from=build_image /workdir/sim_telarray/ /workdir/sim_telarray/
WORKDIR /workdir

RUN microdnf update -y && microdnf install -y \
    bc \
    zstd \
    gsl-devel \
    gcc-fortran \
    procps \
    findutils \
    gcc-c++ \
    libgfortran && \
    microdnf clean all && \
    rm -rf /var/cache/dnf/* /tmp/* /var/tmp/*

ENV SIMTEL_PATH="/workdir/sim_telarray"
