#!/bin/bash
#
# Quantum Package configuration script
#


export QP_ROOT="$( cd "$(dirname "$0")" ; pwd -P )"
echo "QP_ROOT="$QP_ROOT
unset CC
unset CCXX

TREXIO_VERSION=2.3.2

# Force GCC instead of ICC for dependencies
export CC=gcc

# Download submodules
git submodule init
git submodule update

# Update ARM or x86 dependencies
SYSTEM=$(uname -s)
if [[ $SYSTEM = "Linux" ]] ; then
  SYSTEM=""
fi
ARCHITECTURE=$(uname -m)$SYSTEM
cd ${QP_ROOT}/external/qp2-dependencies
git checkout master
git pull
echo "Architecture: $ARCHITECTURE"
cd ${QP_ROOT}


function help()
{
    cat <<EOF
Quantum Package configuration script.

Usage:
  $(basename $0) -c <file>    
  $(basename $0) -h           
  $(basename $0) -i <package> 

Options:
  -c  <file>    Define a COMPILATION configuration file,
                in "${QP_ROOT}/config/".
  -h            Print the HELP message
  -i <package>  INSTALL <package>. Use at your OWN RISK:
                no support will be provided for the installation of
                dependencies.

Example:
  ./$(basename $0) -c config/gfortran.cfg

Note:
  Users are encouraged to create their own configuration files instead of
  modifying the existing ones.

EOF
    exit
}

function error() {
    >&2 echo "$(basename $0): $@"
    exit 2
}

function execute () {
    local _command
    echo "Executing:"
    while read -r line; do
      echo "  " $line
      _command+="${line} ;"
    done
    sleep 1
    echo ""
    printf "\e[0;94m"
    ( eval "set -x ; $_command set +x" ) || exit -1
    printf "\e[m"
    echo ""
}

PACKAGES=""


while getopts "d:c:i:h" c ; do
    case "$c" in
        c)
            case "$OPTARG" in
                "") help ; break;;
                *) if [[ -f $OPTARG ]] ; then
                      CONFIG="$OPTARG"
                   else
                      error "error: configuration file $OPTARG not found."
                      exit 1
                   fi
            esac;;
        i)
            case "$OPTARG" in
                "") help ; break;;
                *) PACKAGES="${PACKAGE} $OPTARG"
            esac;;
        h)
            help
            exit 0;;
        *)
            error $(basename $0)": unknown option $c, try -h for help"
            exit 2;;
    esac
done

# Trim leading and trailing spaces
PACKAGES=$(echo $PACKAGES | xargs)

echo "export QP_ROOT=\"$QP_ROOT\"" > ${QP_ROOT}/etc/00.qp_root.rc

source ${QP_ROOT}/quantum_package.rc



function fail() {
        echo "You can try to install it using the -i option."
        echo "Please refer to INSTALL.rst to install the missing dependencies."
        exit -1
}

function success() {
        echo ""
        echo "Configuration successful."
        exit 0
}

function not_found() {
   echo 'not_found'
}

function find_exe() {
        which $1 2> /dev/null || not_found
}

function find_python_lib() {
        python3 -c "import $1" &> /dev/null && echo "$1" || not_found
}

function find_lib() {
        echo "int main() { return 0; }" > "${QP_ROOT}"/external/tmp.c
        gcc $@ "${QP_ROOT}"/external/tmp.c -o "${QP_ROOT}"/external/tmp.exe 2> /dev/null
        if [[ -x "${QP_ROOT}"/external/tmp.exe ]] ; then
                rm "${QP_ROOT}"/external/tmp.exe "${QP_ROOT}"/external/tmp.c
                echo "$lib"
        else
                rm "${QP_ROOT}"/external/tmp.c
                not_found
        fi
}

function find_dir() {
        if [[ -d $1 ]] ; then
                echo "$1"
        else
                not_found
        fi
}

# Make program believe stdin is a tty
function faketty() {
  script -qfc "$(printf "%q " "$@")" /dev/null
}

# Install IRPF90 if needed
IRPF90=$(find_exe irpf90)
if [[ ${IRPF90} = $(not_found) ]] ; then
        make -C ${QP_ROOT}/external/irpf90
fi



if [[ "${PACKAGES}.x" != ".x" ]] ; then
        printf "\e[0;31m"
        echo ""
      echo "#########################################################"
      echo "#                                                       #"
      echo "#       Automatic installation of dependencies          #"
      echo "#                                                       #"
      echo "# USE AT YOUR OWN RISK :                                #"
      echo "# No support will be provided by the quantum package    #"
      echo "# developers for the installation of external software. #"
      echo "#                                                       #"
      echo "# You may refer to the INSTALL.rst file for help.       #"
      echo "#                                                       #"
      echo "#########################################################"
        printf "\e[m"
        echo ""
        sleep 1
fi

if [[ ${PACKAGES} = all ]] ; then
        PACKAGES="zlib ninja zeromq f77zmq gmp ocaml docopt resultsFile bats trexio"
fi


for PACKAGE in ${PACKAGES} ; do

    if [[ ${PACKAGE} = ninja ]] ; then

            execute << EOF
              rm -f "\${QP_ROOT}"/bin/ninja
              tar -zxvf "\${QP_ROOT}"/external/qp2-dependencies/${ARCHITECTURE}/ninja.tar.gz 
              mv ninja "\${QP_ROOT}"/bin/
EOF

    elif [[ ${PACKAGE} = trexio-nohdf5 ]] ; then

            VERSION=$TREXIO_VERSION
            execute << EOF
              cd "\${QP_ROOT}"/external
              wget https://github.com/TREX-CoE/trexio/releases/download/v${VERSION}/trexio-${VERSION}.tar.gz
              rm -rf trexio-${VERSION}
              tar -zxf trexio-${VERSION}.tar.gz && rm trexio-${VERSION}.tar.gz
              cd trexio-${VERSION}
              ./configure --prefix=\${QP_ROOT} --without-hdf5 CFLAGS='-g'
              make -j 8 && make -j 8 check && make -j 8 install
              tar -zxvf "\${QP_ROOT}"/external/qp2-dependencies/${ARCHITECTURE}/ninja.tar.gz 
              mv ninja "\${QP_ROOT}"/bin/
EOF
    elif [[ ${PACKAGE} = trexio ]] ; then

            VERSION=$TREXIO_VERSION
            execute << EOF
              cd "\${QP_ROOT}"/external
              wget https://github.com/TREX-CoE/trexio/releases/download/v${VERSION}/trexio-${VERSION}.tar.gz
              rm -rf trexio-${VERSION}
              tar -zxf trexio-${VERSION}.tar.gz && rm trexio-${VERSION}.tar.gz
              cd trexio-${VERSION}
              ./configure --prefix=\${QP_ROOT} CFLAGS="-g"
              make -j 8 && make -j 8 check && make -j 8 install
EOF
    elif [[ ${PACKAGE} = qmckl ]] ; then

            VERSION=0.5.4
            execute << EOF
              cd "\${QP_ROOT}"/external
              wget https://github.com/TREX-CoE/qmckl/releases/download/v${VERSION}/qmckl-${VERSION}.tar.gz
              rm -rf qmckl-${VERSION}
              tar -zxf qmckl-${VERSION}.tar.gz && rm qmckl-${VERSION}.tar.gz
              cd qmckl-${VERSION}
              ./configure --prefix=\${QP_ROOT} --enable-hpc --disable-doc CFLAGS='-g'
              make && make -j 4 check && make install
EOF
    elif [[ ${PACKAGE} = qmckl-intel ]] ; then

            VERSION=0.5.4
            execute << EOF
              cd "\${QP_ROOT}"/external
              wget https://github.com/TREX-CoE/qmckl/releases/download/v${VERSION}/qmckl-${VERSION}.tar.gz
              rm -rf qmckl-${VERSION}
              tar -zxf qmckl-${VERSION}.tar.gz && rm qmckl-${VERSION}.tar.gz
              cd qmckl-${VERSION}
              ./configure --prefix=\${QP_ROOT} --enable-hpc --disable-doc --with-icc --with-ifort CFLAGS='-g'
              make && make -j 4 check && make install
EOF
 

    elif [[ ${PACKAGE} = gmp ]] ; then

            execute << EOF
              cd "\${QP_ROOT}"/external
              tar --bzip2 --extract --file qp2-dependencies/gmp-6.1.2.tar.bz2
              cd gmp-6.1.2
              ./configure --prefix=$QP_ROOT && make -j 8
              make -j 8 install
EOF

    elif [[ ${PACKAGE} = zeromq ]] ; then

            execute << EOF
              export CC=gcc
              export CXX=g++
              cd "\${QP_ROOT}"/external
              tar --gunzip --extract --file qp2-dependencies/zeromq-4.2.5.tar.gz
              cd zeromq-*
              [[ "${SYSTEM}" = "Darwin" ]] && ./autogen.sh
              ./configure --prefix="\$QP_ROOT" --without-libsodium --enable-libunwind=no
              make -j 8
              make install
EOF


    elif [[ ${PACKAGE} = f77zmq ]] ; then

            execute << EOF
              cd "\${QP_ROOT}"/external
              tar --gunzip --extract --file qp2-dependencies/f77-zmq-4.3.?.tar.gz
              cd f77-zmq-*
              ./configure --prefix=\$QP_ROOT
              export ZMQ_H="\$QP_ROOT"/include/zmq.h
              make && make check && make install
EOF


    elif [[ ${PACKAGE} = ocaml ]] ; then

         execute <<EOF
            source "${QP_ROOT}"/quantum_package.rc
            rm -rf "${QP_ROOT}"/external/opampack
            cd "${QP_ROOT}"/external/
            tar --gunzip --extract --file qp2-dependencies/${ARCHITECTURE}/opampack.tar.gz
            cd "${QP_ROOT}"/external/opampack
            ./install.sh
            export OPAMROOT="${QP_ROOT}"/external/opampack/opamroot
            eval \$("${QP_ROOT}"/external/opampack/opam env)
EOF

    elif [[ ${PACKAGE} = bse ]] ; then

            execute << EOF
              cd "\${QP_ROOT}"/external
              tar --gunzip --extract --file qp2-dependencies/bse-v0.8.11.tar.gz
              python3 -m pip install -e basis_set_exchange-*
EOF

    elif [[ ${PACKAGE} = zlib ]] ; then

            execute << EOF
              cd "\${QP_ROOT}"/external
              tar --gunzip --extract --file qp2-dependencies/zlib-1.2.11.tar.gz
              cd zlib-*/
              ./configure --prefix=${QP_ROOT} && \
              make && make install
EOF


    elif [[ ${PACKAGE} = docopt ]] ; then

            execute << EOF
              cd "\${QP_ROOT}"/external
              tar --gunzip --extract --file qp2-dependencies/docopt-0.6.2.tar.gz
              mv docopt-*/docopt.py "\${QP_ROOT}/external/Python"
EOF


    elif [[ ${PACKAGE} = resultsFile ]] ; then

            execute << EOF
              cd "\${QP_ROOT}"/external
              tar --gunzip --extract --file qp2-dependencies/resultsFile-v2.3.tar.gz
              mv resultsFile-*/resultsFile "\${QP_ROOT}/external/Python/"
EOF

    elif [[ ${PACKAGE} = bats ]] ; then

            execute << EOF
              cd "\${QP_ROOT}"/external
              tar -zxf qp2-dependencies/bats-v1.7.0.tar.gz
              ( cd bats-core-1.7.0/ ; ./install.sh \${QP_ROOT})
EOF

    else
        error "${PACKAGE} unknown."
        fail
    fi


done

source ${QP_ROOT}/quantum_package.rc

NINJA=$(find_exe ninja)
if [[ ${NINJA} = $(not_found) ]] ; then
        error "Ninja (ninja) is not installed."
        fail
fi

ZEROMQ=$(find_lib -lzmq)
if [[ ${ZEROMQ} = $(not_found) ]] ; then

        MAKE=$(find_exe make)
        if [[ ${MAKE} = $(not_found) ]] ; then
                error "make is not installed."
                fail
        fi

        M4=$(find_exe autoreconf)
        if [[ ${M4} = $(not_found) ]] ; then
                error "autoreconf is not installed."
                fail
        fi

        M4=$(find_exe m4)
        if [[ ${M4} = $(not_found) ]] ; then
                error "m4 preprocesssor is not installed."
                fail
        fi

        error "ZeroMQ (zeromq) is not installed."
        fail
fi

TREXIO=$(find_lib -ltrexio)
if [[ ${TREXIO} = $(not_found) ]] ; then
        error "TREXIO (trexio | trexio-nohdf5) is not installed. If you don't have HDF5, use trexio-nohdf5"
        fail
fi

#QMCKL=$(find_lib -lqmckl)
#if [[ ${QMCKL} = $(not_found) ]] ; then
#        error "QMCkl (qmckl | qmckl-intel) is not installed."
#        fail
#fi

F77ZMQ=$(find_lib -lzmq -lf77zmq -lpthread)
if [[ ${F77ZMQ} = $(not_found) ]] ; then
        error "Fortran binding of ZeroMQ (f77zmq) is not installed."
        fail
fi

GMP=$(find_lib -lgmp)
if [[ ${ZLIB} = $(not_found) ]] ; then
        error "GMP (gmp) is not installed."
        fail
fi

OCAML=$(find_exe ocamlc)
if [[ ${OCAML} = $(not_found) ]] ; then
        error "OCaml (ocaml) compiler is not installed."
        fail
fi

ZLIB=$(find_lib -lz)
if [[ ${ZLIB} = $(not_found) ]] ; then
        error "Zlib (zlib) is not installed."
        fail
fi

DOCOPT=$(find_python_lib docopt)
if [[ ${DOCOPT} = $(not_found) ]] ; then
        error "docopt (docopt) is not installed."
        fail
fi

RESULTSFILE=$(find_python_lib resultsFile)
if [[ ${RESULTSFILE} = $(not_found) ]] ; then
        error "resultsFile (resultsFile) is not installed."
        fail
fi

printf "\e[0;34m"
echo "  ___________________________  "
echo "< All dependencies installed. >"
echo "  ---------------------------  "
echo "         \   ^__^              "
echo "          \  (oo)\_______      "
echo "             (__)\       )\/\. "
echo "                 ||----w |     "
echo "                 ||     ||     "
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo ""
echo "If you have PIP, you can install the Basis Set Exchange command-line tool:"
echo ""
echo "  ./configure -i bse"
echo ""
echo "This will enable the usage of qp_basis to install extra basis sets."
echo ""
echo ""
printf "\e[m\n"


if [[ -n $CONFIG ]] ; then

        "${QP_ROOT}"/scripts/compilation/qp_create_ninja create --development "${CONFIG}"
fi

if [[ -f ${QP_ROOT}/build.ninja ]] ; then
  [[ -z ${TRAVIS} ]] && echo "You can now run ./bin/qpsh to enter in the QP shell mode :)"
else
      echo ""
      echo "${QP_ROOT}/build.ninja does not exist,"
      echo "you need to specify the COMPILATION configuration file."
      echo "See  ./configure -h  for more details."
      echo ""
fi

exit 0