#!/bin/bash
#
# install_netcdf_fj.sh – build NetCDF from source using Fujitsu compilers
#
# Requires the following environment variables (set in ~/.bashrc or exported
# before calling this script):
#   MY_USER     – your Fugaku username
#   MY_PROJECT  – your project code 
#   MY_VOLUME   – your storage volume
#
# The script builds zlib, HDF5, NetCDF-C, and NetCDF-Fortran in sequence,
# installs everything under ${WORK_DIR}/install, and writes a small
# environment file (netcdf_env.sh) that get_siesta_fj.sh sources later.
#

set -e

# Disable HugePages (avoids warnings on Fugaku compute nodes)
export XOSOPTION="off"
export XOS_MMM_L_HPAGE_TYPE="none"

###############################################################################
# Check required environment variables
###############################################################################
for var in MY_USER MY_PROJECT MY_VOLUME; do
  if [[ -z "${!var:-}" ]]; then
    echo "Error: environment variable ${var} is not set." >&2
    echo "Export it or add it to your ~/.bashrc before running this script." >&2
    exit 1
  fi
done

echo "=========================================="
echo "NetCDF installation – Fujitsu toolchain"
echo "=========================================="

###############################################################################
# Paths
###############################################################################
BASE_DIR="/${MY_VOLUME}/mdt1/data/${MY_PROJECT}/${MY_USER}"
WORK_DIR="${BASE_DIR}/netcdf_fujitsu"
SRC_DIR="${WORK_DIR}/src"
INSTALL_DIR="${WORK_DIR}/install"

FUJITSU_DIR="/opt/FJSVxtclanga/tcsds-1.2.42"

###############################################################################
# Library versions
###############################################################################
ZLIB_VERSION="1.3.1"
HDF5_VERSION="1.14.3"
NETCDF_C_VERSION="4.9.2"
NETCDF_FORTRAN_VERSION="4.6.1"

###############################################################################
# Download URLs
###############################################################################
ZLIB_URL="https://zlib.net/fossils/zlib-${ZLIB_VERSION}.tar.gz"
HDF5_URL="https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.14/hdf5-${HDF5_VERSION}/src/hdf5-${HDF5_VERSION}.tar.gz"
NETCDF_C_URL="https://downloads.unidata.ucar.edu/netcdf-c/${NETCDF_C_VERSION}/netcdf-c-${NETCDF_C_VERSION}.tar.gz"
NETCDF_FORTRAN_URL="https://downloads.unidata.ucar.edu/netcdf-fortran/${NETCDF_FORTRAN_VERSION}/netcdf-fortran-${NETCDF_FORTRAN_VERSION}.tar.gz"

###############################################################################
# Environment
###############################################################################
export PATH="${FUJITSU_DIR}/bin:${INSTALL_DIR}/bin:${PATH}"
export LD_LIBRARY_PATH="${INSTALL_DIR}/lib:${FUJITSU_DIR}/lib64:${LD_LIBRARY_PATH:-}"

mkdir -p "${SRC_DIR}" "${INSTALL_DIR}"

###############################################################################
# Helper: download and extract a tarball
###############################################################################
download_and_extract() {
    local url=$1
    local filename
    filename=$(basename "$url")
    cd "${SRC_DIR}"
    if [ ! -f "${filename}" ]; then
        echo "Downloading ${filename} ..."
        wget "${url}" || curl -L -O "${url}"
    else
        echo "${filename} already downloaded."
    fi
    echo "Extracting ${filename} ..."
    tar -xzf "${filename}"
}

###############################################################################
# zlib
###############################################################################
install_zlib() {
    echo ""
    echo "=========================================="
    echo "Installing zlib ${ZLIB_VERSION}"
    echo "=========================================="

    download_and_extract "${ZLIB_URL}"
    cd "${SRC_DIR}/zlib-${ZLIB_VERSION}"

    CC=fcc \
    CFLAGS="-Nclang -O2 -fPIC" \
    ./configure --prefix="${INSTALL_DIR}" --static

    make -j 4
    make install
    echo "✓ zlib installed"
}

###############################################################################
# HDF5
###############################################################################
install_hdf5() {
    echo ""
    echo "=========================================="
    echo "Installing HDF5 ${HDF5_VERSION}"
    echo "=========================================="

    download_and_extract "${HDF5_URL}"
    cd "${SRC_DIR}/hdf5-${HDF5_VERSION}"

    echo "Configuring HDF5 (static libraries, parallel Fortran) ..."

    CC=mpifcc \
    FC=mpifrt \
    CFLAGS="-Nclang -O2 -fPIC" \
    FCFLAGS="-O2 -fPIC" \
    ./configure --prefix="${INSTALL_DIR}" \
                --enable-fortran \
                --enable-parallel \
                --disable-shared \
                --enable-static \
                --enable-hl \
                --with-zlib="${INSTALL_DIR}"

    if [ $? -ne 0 ]; then
        echo "✗ HDF5 configure failed. Last 100 lines of config.log:"
        tail -100 config.log
        exit 1
    fi

    echo "Building HDF5 (this may take 10-15 minutes) ..."
    make -j 4 || { make clean && make -j 1; }

    echo "Installing HDF5 ..."
    make install

    echo "✓ HDF5 installed"
    ls -lh "${INSTALL_DIR}/lib/libhdf5"* | head -5
}

###############################################################################
# NetCDF-C
###############################################################################
install_netcdf_c() {
    echo ""
    echo "=========================================="
    echo "Installing NetCDF-C ${NETCDF_C_VERSION}"
    echo "=========================================="

    download_and_extract "${NETCDF_C_URL}"
    cd "${SRC_DIR}/netcdf-c-${NETCDF_C_VERSION}"

    echo "Configuring NetCDF-C ..."

    CC=mpifcc \
    CFLAGS="-Nclang -O2 -fPIC" \
    CPPFLAGS="-I${INSTALL_DIR}/include" \
    LDFLAGS="-L${INSTALL_DIR}/lib" \
    LIBS="-lhdf5_hl -lhdf5 -lz -lm" \
    ./configure --prefix="${INSTALL_DIR}" \
                --enable-netcdf-4 \
                --disable-shared \
                --enable-static \
                --disable-dap \
                --disable-byterange \
                --disable-libxml2

    if [ $? -ne 0 ]; then
        echo "✗ NetCDF-C configure failed. Last 100 lines of config.log:"
        tail -100 config.log
        exit 1
    fi

    echo "Building NetCDF-C ..."
    make -j 4

    echo "Installing NetCDF-C ..."
    make install

    echo "✓ NetCDF-C installed"

    if [ -f "${INSTALL_DIR}/bin/nc-config" ]; then
        echo "nc-config --version: $("${INSTALL_DIR}/bin/nc-config" --version)"
        echo "nc-config --libs:    $("${INSTALL_DIR}/bin/nc-config" --libs)"
    fi
}

###############################################################################
# NetCDF-Fortran
###############################################################################
install_netcdf_fortran() {
    echo ""
    echo "=========================================="
    echo "Installing NetCDF-Fortran ${NETCDF_FORTRAN_VERSION}"
    echo "=========================================="

    download_and_extract "${NETCDF_FORTRAN_URL}"
    cd "${SRC_DIR}/netcdf-fortran-${NETCDF_FORTRAN_VERSION}"

    export NCDIR="${INSTALL_DIR}"

    if [ -f "${INSTALL_DIR}/bin/nc-config" ]; then
        NC_LIBS=$(${INSTALL_DIR}/bin/nc-config --libs)
        echo "Using nc-config --libs: ${NC_LIBS}"
    else
        NC_LIBS="-lnetcdf -lhdf5_hl -lhdf5 -lz -lm"
        echo "nc-config not available; using default LIBS."
    fi

    CC=mpifcc \
    FC=mpifrt \
    F77=mpifrt \
    CFLAGS="-Nclang -O2 -fPIC" \
    FCFLAGS="-O2 -fPIC" \
    FFLAGS="-O2 -fPIC" \
    CPPFLAGS="-I${INSTALL_DIR}/include" \
    LDFLAGS="-L${INSTALL_DIR}/lib" \
    LIBS="${NC_LIBS}" \
    ./configure --prefix="${INSTALL_DIR}" \
                --disable-shared \
                --enable-static

    if [ $? -ne 0 ]; then
        echo "✗ NetCDF-Fortran configure failed. Last 100 lines of config.log:"
        tail -100 config.log
        exit 1
    fi

    echo "Building NetCDF-Fortran ..."
    make -j 4

    echo "Installing NetCDF-Fortran ..."
    make install

    echo "✓ NetCDF-Fortran installed"
}

###############################################################################
# Write environment file sourced by get_siesta_fj.sh
###############################################################################
create_env_file() {
    echo ""
    echo "Writing environment file ..."
    ENV_FILE="${WORK_DIR}/netcdf_env.sh"

    # Use a temporary variable so the heredoc expands MY_* at write time,
    # but keeps NETCDF_DIR and FUJITSU_DIR as literals for later sourcing.
    cat > "${ENV_FILE}" << ENVEOF
#!/bin/bash
# netcdf_env.sh – sourced by get_siesta_fj.sh to expose NetCDF paths.
# Generated by install_netcdf_fj.sh on $(date).

# Disable HugePages warnings
export XOSOPTION="off"
export XOS_MMM_L_HPAGE_TYPE="none"

export NETCDF_DIR="${INSTALL_DIR}"
export FUJITSU_DIR="/opt/FJSVxtclanga/tcsds-1.2.42"

export PATH="\${FUJITSU_DIR}/bin:\${NETCDF_DIR}/bin:\${PATH}"
export LD_LIBRARY_PATH="\${NETCDF_DIR}/lib:\${FUJITSU_DIR}/lib64:\${LD_LIBRARY_PATH:-}"

export NETCDF_INC="-I\${NETCDF_DIR}/include"
export NETCDF_LIB="-L\${NETCDF_DIR}/lib -lnetcdff -lnetcdf -lhdf5_hl -lhdf5 -lz -lm"

echo "NetCDF environment configured."
echo "  NETCDF_DIR : \${NETCDF_DIR}"
ENVEOF

    chmod +x "${ENV_FILE}"
    echo "✓ Environment file written: ${ENV_FILE}"
}

###############################################################################
# Verify critical libraries
###############################################################################
verify_installation() {
    echo ""
    echo "=========================================="
    echo "Verifying installation"
    echo "=========================================="

    if [ -f "${INSTALL_DIR}/bin/nc-config" ]; then
        echo "nc-config --version: $("${INSTALL_DIR}/bin/nc-config" --version)"
        echo "nc-config --libs:    $("${INSTALL_DIR}/bin/nc-config" --libs)"
    fi

    if [ -f "${INSTALL_DIR}/bin/nf-config" ]; then
        echo "nf-config --version: $("${INSTALL_DIR}/bin/nf-config" --version)"
        echo "nf-config --flibs:   $("${INSTALL_DIR}/bin/nf-config" --flibs)"
    fi

    echo ""
    echo "Installed libraries:"
    ls -lh "${INSTALL_DIR}/lib/"*.a 2>/dev/null | grep -E "libz|libhdf5|libnetcdf"

    echo ""
    CRITICAL_FILES=(
        "${INSTALL_DIR}/lib/libz.a"
        "${INSTALL_DIR}/lib/libhdf5.a"
        "${INSTALL_DIR}/lib/libhdf5_hl.a"
        "${INSTALL_DIR}/lib/libhdf5_fortran.a"
        "${INSTALL_DIR}/lib/libnetcdf.a"
        "${INSTALL_DIR}/lib/libnetcdff.a"
    )

    ALL_OK=true
    for f in "${CRITICAL_FILES[@]}"; do
        if [ -f "$f" ]; then
            echo "  ✓ $(basename "$f")"
        else
            echo "  ✗ Missing: $(basename "$f")"
            ALL_OK=false
        fi
    done

    if [ "${ALL_OK}" = true ]; then
        echo ""
        echo "✓ All critical libraries present."
    fi
}

###############################################################################
# Main
###############################################################################
main() {
    echo "Start: $(date)"
    echo ""

    install_zlib
    install_hdf5
    install_netcdf_c
    install_netcdf_fortran
    create_env_file
    verify_installation

    echo ""
    echo "=========================================="
    echo "✓ Installation complete"
    echo "=========================================="
    echo ""
    echo "Elapsed: ${SECONDS} seconds"
    echo ""
    echo "To use:  source ${WORK_DIR}/netcdf_env.sh"
}

LOG_FILE="${WORK_DIR}/install_log_$(date +%Y%m%d_%H%M%S).txt"
mkdir -p "${WORK_DIR}"
main 2>&1 | tee "${LOG_FILE}"