#!/usr/bin/env bash

# Build hscPipe.
# Before executing this script, prepare the environment according to pre-build.txt
#
# NOTE:
#   In the following script,
#   EXPORTed variables MUST be exported. DO NOT MAKE LIGHT OF IT.

#
# parameters
#

set -eu

if ! declare -A test_bash_assocArray &> /dev/null
then
    echo "The running bash does not support associative arrays (declare -A)." >&2
    echo "Use the latest bash instead." >&2
    exit 1
fi

[[ -e "./config.rc" ]] || {
    echo "Copy config.rc into the current directory before executing this script" >&2
    exit 1
}
source ./config.rc
source $scriptdir/openblas/openblas.rc

if [[ $useLatest == "false" ]]
then
    declare updatesDir="/dev/null"
else
    declare updatesDir="$scriptdir/updates"
fi

declare eupsTagName=1.5.9
declare progressFile=$builddir/progress.txt

# include progress of previous run
[[ -e $progressFile ]] && . $progressFile

# Set error handler
OnError()
{
    # When the script is about to abort
    if [[ "$-" == *e* ]]
    then
        echo    "Build failed." >&2
        echo    "Check for the error messages and make appropriate modifications." >&2
        echo -n "After that you can re-execute this script." >&2
        echo -n "  This script will automatically skip what have already been done," >&2
        echo    " and start from the point of the previous failure." >&2
        echo -n "If this functionality is undesirable, modify (or simply delete) $progressFile, " >&2
        echo    " in which finished things have been registered." >&2
    fi
}

trap OnError ERR

# install hacked commands into a temporary directory
if [[ ${done30:-false} != "true" ]]
then
    mkdir -p $builddir/bin
    yes | cp $scriptdir/bin/* $builddir/bin/
    chmod a+x $builddir/bin/*
    echo 'done30=true' >> $progressFile
fi

# cleanse PATH
if [[ -z "${systemPath:-}" ]]
then
    systemPath="/usr/bin:/bin"
fi

bash_dir="$(dirname "$BASH")"
if [[ ":$builddir/bin:$systemPath:" == *:"$bash_dir":* ]]
then
    export PATH="$builddir/bin:$systemPath"
else
    export PATH="$builddir/bin:$bash_dir:$systemPath"
fi

export -n CPATH
export -n C_INCLUDE_PATH
export -n CPLUS_INCLUDE_PATH
export -n LIBRARY_PATH
export -n LD_LIBRARY_PATH
export -n LD_RUN_PATH

# prepare EUPS_PATH
if [[ ${done40:-false} != "true" ]]
then
    mkdir -p $builddir/EupsBuildDir
    mkdir -p "$EUPS_PATH"
    cd "$EUPS_PATH"
    ln -s $builddir/EupsBuildDir .
    echo 'done40=true' >> $progressFile
fi

# install eups (initial one)
if [[ ${done50:-false} != "true" ]]
then
    cd $builddir
    wget https://github.com/RobertLuptonTheGood/eups/archive/$eupsTagName.zip -O eups-$eupsTagName.zip
    unzip eups-$eupsTagName

    eupsVer=( $(< eups-$eupsTagName/git.version) )
    echo "eupsVer=$eupsVer" >> $progressFile

    cd eups-$eupsTagName

    export EUPS_PATH
    ./configure --prefix=$EUPS_PATH/eups/$eupsVer --with-python=$(which python)
    make
    make install
    cd $builddir
    echo 'done50=true' >> $progressFile
fi

# copy files in EUPS_PATH
if [[ ${done55:-false} != "true" ]]
then
    # Copy bashrc
    cat $scriptdir/bashrc.in |
        sed "s:@EUPS_PATH@:$EUPS_PATH:g" |
        sed "s:@PIPEVERSION@:$hscPipeVer:g" |
        sed "s:@EUPSVERSION@:$eupsVer:g" > $EUPS_PATH/bashrc

    # Copy post-install.sh
    cat $scriptdir/post-install.sh.in |
        sed "s:@EUPS_PATH_SPLIT@:${EUPS_PATH:0:(${#EUPS_PATH}+1)/2}''${EUPS_PATH:(${#EUPS_PATH}+1)/2}:g" > $EUPS_PATH/post-install.sh
    chmod a+x $EUPS_PATH/post-install.sh

    echo "undefined" > $EUPS_PATH/.post-install.state

    # Copy README
    cp $scriptdir/README $EUPS_PATH/
    cp $scriptdir/LICENSE $EUPS_PATH/
    cp $scriptdir/gpl.txt $EUPS_PATH/

    cp $scriptdir/install-astrometry_net_data.sh $EUPS_PATH/
    chmod a+x $EUPS_PATH/install-astrometry_net_data.sh

    cp -R $scriptdir/toppings $EUPS_PATH/

    # Copy OS's signature so that we can know which version
    # users have installed when they ask us questions
    mkdir $EUPS_PATH/.signature
    for i in /etc/*release /etc/*version
    do
        if [[ -f "$i" ]]
        then
            cp "$i" $EUPS_PATH/.signature/ || true
        fi
    done

    # Generate manifest.remap (which is used not by us but by advanced users)
    if [[ -z "${mkldir:-}" ]]
    then
        bash $builddir/bin/generate-remap.sh mkl-openblas:$openblas_ver $updatesDir > $EUPS_PATH/manifest.remap
    else
        bash $builddir/bin/generate-remap.sh $updatesDir > $EUPS_PATH/manifest.remap
    fi

    echo 'done55=true' >> $progressFile
fi

# acquire package info
if [[ ${done65:-false} != "true" ]]
then
    cd $builddir
    rm -rf hsca.ipmu.jp/
    bash $builddir/bin/download-manifests.sh hsca.ipmu.jp/sumire/packages hscPipe $hscPipeVer

    declare -A prodVer

    # get build files etc.
    while read -r package_ flavor_ version_ table_ dir_ id_
    do
        if [[ -z "$package_" || "$package_" == "#"* ]]
        then
            continue
        fi
        prodVer[${package_}]=${version_}
    done <<< "$(< hsca.ipmu.jp/sumire/packages/manifests/hscPipe-$hscPipeVer.manifest)"

    # inject hacked builds & manifests
    yes | cp $scriptdir/mybuilds/*.build  hsca.ipmu.jp/sumire/packages/builds/
    yes | cp $scriptdir/mybuilds/*.manifest  hsca.ipmu.jp/sumire/packages/manifests/

    if [[ -z "${mkldir:-}" ]]
    then
        # replace MKL -> openblas
        egrep -l -r '^mkl[ \t]' hsca.ipmu.jp/sumire/packages/manifests/ | while read -r file
        do
            echo patching "$file"...
            mv ${file} ${file}~
            cat ${file}~ | sed 's/^mkl[ \t].*$/'"openblas generic $openblas_ver none none search/" > ${file}
            rm ${file}~
        done
    fi

    # Update third-party packages
    find $updatesDir -name "*.build" -print0 | while read -d '' build_
    do
        declare base_="$(basename "${build_}")"
        base_=${base_:0:${#base_}-6}
        declare version_=${base_#*-}
        declare package_=${base_:0:${#base_}-${#version_}-1}

        echo updating $package_ to $version_

        cat $build_ | sed "s/@VERSION@/${version_}/g" > hsca.ipmu.jp/sumire/packages/builds/${base_}.build
        mv hsca.ipmu.jp/sumire/packages/tables/${package_}-${prodVer[${package_}]}.table hsca.ipmu.jp/sumire/packages/tables/${base_}.table
        mv hsca.ipmu.jp/sumire/packages/manifests/${package_}-${prodVer[${package_}]}.manifest hsca.ipmu.jp/sumire/packages/manifests/${base_}.manifest

        egrep -l -r "^${package_}"'[ \t]' hsca.ipmu.jp/sumire/packages/manifests/ | while read -r file
        do
            echo patching "$file"...
            mv ${file} ${file}~
            cat ${file}~ | sed "s/^${package_}"'[ \t].*$/'"${package_} generic ${version_} ${package_}-${version_}.table none build:${package_}-${version_}.build/" > ${file}
            rm ${file}~
        done
    done

    echo 'done65=true' >> $progressFile
fi

# setup eups
prerequisite=($EUPS_PATH/*/python/*/lib $EUPS_PATH/*/tcltk/*/lib)
LD_LIBRARY_PATH=
for pre in "${prerequisite[@]}"
do
    if [[ -e "$pre" ]]
    then
        LD_LIBRARY_PATH+=":$pre"
    fi
done
if [[ -n $LD_LIBRARY_PATH ]]
then
    LD_LIBRARY_PATH="${LD_LIBRARY_PATH:1}"
    export LD_LIBRARY_PATH
fi

set +u
. $EUPS_PATH/eups/$eupsVer/bin/setups.sh || true
set -u
export EUPS_PKGROOT="$builddir/hsca.ipmu.jp/sumire/packages/"

function GetVersion()
{
    declare package="$1"
    declare a
    declare b
    declare c
    declare d
    read -r a b c d <<< $(egrep '^[ \t]*'$package'[ \t]' $EUPS_PKGROOT/manifests/hscPipe-$hscPipeVer.manifest)
    echo $c
}

#install gcc
if [[ ${done107:-false} != "true" ]]
then
    eups distrib install gcc $(GetVersion gcc)

    # hack gcc temporarily so that it ignores -march=native option
    pushd $EUPS_PATH/$(eups flavor)/gcc/*/bin
    for i in gcc g++ cc c++
    do
        if [[ -e $i ]]
        then
            mv "$i" "$i-temp"
            cat > "$i" << EOF
#!/usr/bin/env bash
args=()
for i in "\$@"
do
    if [[ "\$i" != "-march=native" ]]
    then
        args+=("\$i")
    fi
done

exec "$PWD/$i-temp" "\${args[@]}"
EOF
            chmod u+x "$i"
        fi
    done
    popd

    echo 'done107=true' >> $progressFile
fi
export -n CC
export -n CXX
setup gcc

# install openblas
if [[ ${done113:-false} != "true" ]]
then
    if [[ -z "${mkldir:-}" ]]
    then
        builddir=$builddir bash $scriptdir/openblas/build-openblas.sh
    else
        mkl_product_dir="$EUPS_PATH/$(eups flavor)/mkl/$(GetVersion mkl)"
        bash $builddir/bin/create-ups-for-mkl.sh "$mkldir" "$mkl_product_dir"
        eups declare -r "$mkl_product_dir" mkl $(GetVersion mkl)
    fi
    echo 'done113=true' >> $progressFile
fi

if [[ -z "${mkldir:-}" ]]
then
    setup openblas
else
    setup mkl
fi

# install python
if [[ ${done120:-false} != "true" ]]
then
    eups distrib install python $(GetVersion python)
    echo 'done120=true' >> $progressFile
fi

setup python

# install eups (second one)
if [[ ${done127:-false} != "true" ]]
then
    cd $builddir/eups-$eupsTagName
    ./configure --prefix=$EUPS_PATH/eups/$eupsVer --with-python=$(which python)
    make
    make install
    cd $builddir
    echo 'done127=true' >> $progressFile
fi

# install matplotlib
if [[ ${done142:-false} != "true" ]]
then
    eups distrib install matplotlib $(GetVersion matplotlib)
    echo 'done142=true' >> $progressFile
fi

# declare astrometry_net_data
if [[ ${done149:-false} != "true" ]]
then
    eups declare -m none -r none astrometry_net_data None
    echo 'done149=true' >> $progressFile
fi

setup astrometry_net_data None

# install hscPipe
if [[ ${done158:-false} != "true" ]]
then
    eups distrib install hscPipe $hscPipeVer
    echo 'done158=true' >> $progressFile
fi

# uninstall hack from gcc
if [[ ${done305:-false} != "true" ]]
then
    pushd $EUPS_PATH/$(eups flavor)/gcc/*/bin
    for tmp in *-temp
    do
        if [[ -e "$tmp" ]]
        then
            i="${tmp:0:${#tmp}-5}"
            rm -f "$i"
            mv "$tmp" "$i"
        fi
    done
    popd

    echo 'done305=true' >> $progressFile
fi

echo OK
