#!/usr/bin/env bash

set -euo pipefail


#######################################################################
#                                Help                                 #
#######################################################################

function usage()
{
    echo "Script to synchronize the codes between your computer"
    echo "and servers (vortex, snowtools, other codes)"
    echo ""
    echo "$0 [options] folder server"
    echo ""
    echo -e "options:"
    echo -e "\t-h --help : help"
    # echo -e "\t--no-delete : Do not delete files on destination (not implemented)"
    echo -e "\t-f --force : Do not ask for confirmation"
    echo -e "\t--ftp : Use lftp/mirror to transfer files instead of rsync"
    echo -e ""
    echo -e "folder:"
    echo -e "\tThe code folder to synchronize"
    echo -e "\tAlso accept 'snowtools', 'surfex' and 'vortex' if"
    echo -e "\tenvironment variables SNOWTOOLS_CEN, EXESURFEX and"
    echo -e "\tVORTEX are defined"
    echo -e ""
    echo -e "server:"
    echo -e "\tThe server on which the code should be sent"
    echo -e ""
}

#######################################################################
#                            Colored terms                            #
#######################################################################

if [[ -t 1 ]]
then
    GREEN="\033[32m"
    ORANGE="\033[1;33m"
    RED="\033[1;31m"
    STOPC="\033[0m"
else
    GREEN=""
    ORANGE=""
    RED=""
    STOPC=""
fi

#######################################################################
#                          Parsing arguments                          #
#######################################################################
FOLDER='x'
SERVER='x'
FORCE=0
METHOD='Rsync'
while [[ $# -gt 0 ]]
do
key="$1"

case $key in
    -h|--help)
        usage
        exit 0
    ;;
    -f|--force)
        FORCE=1
        shift
    ;;
    --ftp)
        METHOD='LFTP'
        shift
    ;;
    -*)
        echo -e "${RED}ERROR${STOPC}: Unknown argument $1"
        echo ""
        usage
        exit 3
    ;;
    *)  # Folder or server
        if [ "$FOLDER" = "x" ]
        then
            FOLDER="$1"
        else
            SERVER="$1"
        fi
        shift # shift to next argument
    ;;
esac
done

#######################################################################
#                           Check arguments                           #
#######################################################################
# We need at least folder and server


if [ "$SERVER" = "x" ]
then
        echo -e "${RED}ERROR${STOPC}: Argument server not provided"
        echo ""
        usage
        exit 3
fi

# Check FOLDER : is it a known repository ? Or a valid folder ?

case $FOLDER in
    x)
        echo -e "${RED}ERROR${STOPC}: Argument folder not provided"
        echo ""
        usage
        exit 3
    ;;
    vortex)
        if [ ! -d "$FOLDER" ]
        then
            FOLDER="$VORTEX"
        fi
    ;;
    snowtools)
        if [ ! -d "$FOLDER" ]
        then
            FOLDER="$SNOWTOOLS_CEN"
        fi
    ;;
    surfex)
        if [ ! -d "$FOLDER" ]
        then
            FOLDER=`dirname $EXESURFEX`
        fi
    ;;
esac

if [ ! -d "$FOLDER" ]
then
        echo -e "${RED}ERROR${STOPC}: Folder $FOLDER is incorrect"
        echo ""
        usage
        exit 3
fi

# Pre-processing of FOLDER variable : remove $HOME at begining
FOLDER=`realpath "$FOLDER"`
if $(echo `realpath SURFEX` | grep -q "^$HOME")
then  # The folder to treat is a subfolder of $HOME : OK
    FOLDER_FROM_HOME=`echo "$FOLDER" | sed -e "s#^$HOME/##"`
else
    echo -e "${RED}ERROR${STOPC}: This script is not designed to deal with folders that are not in your home !"
    echo "Provided folder $FOLDER is not in your home."
    echo ""
    exit 3
fi

#######################################################################
#                            File transfer                            #
#######################################################################

folder_dest=$FOLDER_FROM_HOME
folder_orig=$HOME/$FOLDER_FROM_HOME/

# Confirmation
if [ $FORCE -eq 0 ]
then
    echo "> $METHOD transfer folder ~/$FOLDER_FROM_HOME on $SERVER (~/$folder_dest)"
    read -p "Is this correct [Y/n] ? " -n 1 -r CHOICE
    echo ""
    if [[ $CHOICE =~ ^[nN]$ ]]
    then
        echo -e "Aborting."
        exit 0
    fi
fi

# Git management : transfer a minimal information on git status
# on the destination in the ofr of a simple .git_info file.
GIT_INFO_ADDED=1
pushd $folder_orig > /dev/null
if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]
then
    GIT_PRETTYLOG=`git log -1 --date=format:'%Y-%m-%d' --format='%h (%cd)'`
    GIT_BRANCH=`git rev-parse --abbrev-ref HEAD`
    if git status --porcelain --untracked-files=no | grep -q 'M'
    then
        GIT_MODIFIED=' +'
    else
        GIT_MODIFIED=''
    fi
    GIT_STR="$GIT_PRETTYLOG $GIT_BRANCH$GIT_MODIFIED"
    echo "$GIT_STR" > "${folder_orig}/.git_info"
    GIT_INFO_ADDED=0
fi
popd > /dev/null

# Actual transfer
if [ "$METHOD" = "Rsync" ]
then
    set +e
    # --delete-excluded --force (force deletion of dirs even if not empty)
    rsync -av --links --delete \
        --exclude .git \
        --exclude .idea \
        --exclude .settings \
        --exclude build \
        --exclude fail_test --exclude Manual_tests \
        --exclude /exe \
        --exclude "venv*" \
        --exclude "*.pyc" --exclude "*.bak" --exclude "*.sav" --exclude "*.backup" \
        --exclude ".*.swp" --exclude "*~" \
        --exclude "*.egg-info" --exclude "*.o" --exclude "*.bin" --exclude "*.exe" \
        --exclude "interpolation/*.mod" \
        --exclude "interpolation/interpol_*" \
        --exclude "src/dir_obj*" --exclude "exe_*" \
        --exclude 'profile_surfex' --exclude 'profile_surfex-LX*' \
        --exclude "src/LIB/grib_api-*-Source" --exclude "src/LIB/eccodes*" --exclude STRATO \
        --exclude "NO_TRANSFER*" \
        --exclude sphinx \
        --exclude examples \
        $folder_orig $SERVER:$folder_dest
    retcode=$?
    set -e
elif [ "$METHOD" = "LFTP" ]
then
    user=`id -u -n`
    set +e
    lftp -c "set ftp:list-options -a;
    open -u $user@$SERVER -p 8021 ftp://137.129.13.180;
    set ftp:passive-mode false;
    set cmd:fail-exit true;
    set ftp:use-utf8 false;
    # Par defaut les logs sont dans ~/.local/share/lftp/transfer_log
    set log:show-pid true;
    set mirror:sort-by name;
    set mirror:overwrite true;
    lcd ./ ;
    mirror --reverse \
      --delete --use-cache --verbose \
      --allow-chown  --allow-suid --no-umask --parallel=2 \
      --exclude .git/ \
      --exclude .idea/ \
      --exclude .settings/ \
      --exclude build \
      --exclude fail_test  \
      --exclude Manual_tests  \
      --exclude exe/ \
      --exclude-glob venv* \
      --exclude-glob *.pyc \
      --exclude-glob *.bak \
      --exclude-glob *.sav \
      --exclude-glob *.backup \
      --exclude-glob .*.swp \
      --exclude-glob *~ \
      --exclude-glob *.egg-info/ \
      --exclude-glob  *.o \
      --exclude-glob *.bin \
      --exclude-glob *.exe \
      --exclude-glob interpolation/*.mod \
      --exclude-glob interpolation/interpol_* \
      --exclude-glob src/dir_obj*/ \
      --exclude-glob exe_*/ \
      --exclude 'profile_surfex' \
      --exclude-glob 'profile_surfex-LX*' \
      --exclude-glob src/LIB/grib_api-*-Source/ \
      --exclude-glob src/LIB/eccodes* \
      --exclude-glob examples/ \
      --exclude-glob sphinx/ \
      --exclude STRATO \
      --exclude-glob NO_TRANSFER*/ \
      $folder_orig $folder_dest"
    retcode=$?
    set -e
fi

# Cleaning eventual git file added
if [ $GIT_INFO_ADDED -eq 0 ]
then
    rm "${folder_orig}/.git_info"
fi

if [ $retcode -eq 0 ]
then
    echo -e "${GREEN}OK${STOPC}: Transfer successful."
else
    echo -e "${RED}ERROR${STOPC}: An error occured during code synchronization.
    Please refer to output log above. (Return code $retcode)"
fi
