#!/usr/bin/env bash
#
# The directory structure for ODB-mapper one-liner
#
# ODBMAPPER_WORK                              root work directory ( default current dir/odbmapper )
#       |
#       |-- <odbver>                          one dir per OrthoDB version
#             |
#             |-- etc
#             |    |-- orthologer_conf.sh     version dependent config
#             |    |-- orthomapper_levels.sh  OrthoDB node definitions for the given version (softlink)
#             |    |-- orthologer_conf.sh     version dependent config
#             |
#             |-- pipeline                    DIR_PROJECT
#             |    |-- PWC, Sequence, ...     orthologer project structure
#             |
#             |-- data
#             |    |-- tarfiles               where OrthoDB tarfiles are downloaded (DBI_DOWNLOAD)
#             |    |-- eukaryota              untarred eukaryota
#             |    |-- ...
#
# For the first run DIR_ORTHOLOGER should be set using
# > export DIR_ORTHOLOGER=<orthologer install dir>
#

# Set command name.
export CMD_ODBMAP=$(basename "${BASH_SOURCE[0]}")

# orthologer install dir.
export DIR_ORTHOLOGER=${DIR_ORTHOLOGER:="$(cd -P "$(dirname $(readlink -f "${BASH_SOURCE[0]}"))"/../ && pwd)"}

# OrthoDB API version.
export URL_ORTHODB_API_VERSION=${URL_ORTHODB_API_VERSION:='current'}

# ODB-mapper root work directory.
export ODBMAPPER_WORK="${ODBMAPPER_WORK:=$(pwd)/odbmapper}"

# Directory where the above tar-files are expanded.
export MAP_ORTHODB_DATA=${MAP_ORTHODB_DATA:=}

# Directory where OrthoDB tar files are downloaded.
# Set relative MAP_ORTHODB_DATA
export DBI_DOWNLOAD=

# OrthoDB versions allowed
export ODB_VERSIONS=(v11 v12)

#------------------------------------------------------------
# get OrthoDB API version
#------------------------------------------------------------
# 1. from name -> <name>_<odbver>
# 2. if not 1. then set to current and fix it in set_orthodb_api() call.
__odbver0=$(basename "${BASH_SOURCE[0]}" .sh)
__odbver=${__odbver0##*_}
if [[ "$__odbver0" != "$__odbver" ]] && [[ -n $__odbver ]]; then
    export URL_ORTHODB_API_VERSION=$__odbver
fi

#------------------------------------------------------------
# given odbmapper work directory, build dir structure
#------------------------------------------------------------
create_base_env() {
    [[ $# -eq 1 ]] || return 255
    local odbver=$1
    mkdir -p $ODBMAPPER_WORK/$odbver/pipeline      || return 255
    mkdir -p $ODBMAPPER_WORK/$odbver/data          || return 255
    mkdir -p $ODBMAPPER_WORK/$odbver/etc           || return 255
    mkdir -p $ODBMAPPER_WORK/$odbver/data/tarfiles || return 255
    return 0
}

#------------------------------------------------------------
# verify base environment
#------------------------------------------------------------
verify_base_dir() {
    local odbver="$1"
    local d="$ODBMAPPER_WORK/$odbver/$2"
    [[ -d "$d" ]] && return 0
    {
        echo "error: work directory not properly setup"
        echo "error: missing $d"
    } 1>&2
    return 255
}
verify_base_env() {
    [[ $# -eq 1 ]] || return 255
    local odbver="$1"
    verify_base_dir "$odbver" etc           || return 255
    verify_base_dir "$odbver" pipeline      || return 255
    verify_base_dir "$odbver" data          || return 255
    verify_base_dir "$odbver" data/tarfiles || return 255
    local f="$ODBMAPPER_WORK/$odbver/etc/orthomapper_levels.sh"
    [[ -f $f ]] || {
        echo "error: work directory not properly setup"
        echo "error: missing file $f"
        return 255
    } 1>&2
    return 0
}

_IN_CONFIG=0
get_or_add_var() {
    local fconf="$1"
    local var="$2"
    local default="$3"
    local _IN_CONFIG=0
    
    local line=$(grep "^${var}=" "$fconf")    
    if [[ -n $line ]]; then
        _IN_CONFIG=1
        eval $line
    else
        eval "${var}=${default}"
        {
            echo "${var}=${default}"
        } >> "$fconf"
    fi
}
#------------------------------------------------------------
# Set orthologer install dir
#------------------------------------------------------------
set_orthologer_dir() {
    # check if DIR_ORTHOLOGER is found in $ODBMAPPER_WORK/config.sh
    [[ -f "$ODBMAPPER_CONFIG" ]] || {
        touch "$ODBMAPPER_CONFIG"
    }

    get_or_add_var "$ODBMAPPER_CONFIG" "DIR_ORTHOLOGER" "$DIR_ORTHOLOGER"
    [[ -d"$DIR_ORTHOLOGER" ]] && return 0
        
    if (( _IN_CONFIG == 1 )); then
        echo
        echo "ERROR: Found bad DIR_ORTHOLOGER in $ODBMAPPER_CONFIG"
        echo "Set DIR_ORTHOLOGER to a valid directory containing the orthologer software."
        echo
    else
        echo
        echo "ERROR: orthologer install dir is not readable: DIR_ORTHOLOGER=$DIR_ORTHOLOGER"
        echo "       Set it using 'export DIR_ORTHOLOGER=<install dir>'"
        echo
    fi
    return 255
}

#------------------------------------------------------------
# set directory where the OrthoDB data resides
#------------------------------------------------------------
set_map_orthodb_data() {
    [[ -f "$ODBMAPPER_CONFIG" ]] || touch "$ODBMAPPER_CONFIG"
    
    MAP_ORTHODB_DATA=${MAP_ORTHODB_DATA:="$ODBMAPPER_WORK/$URL_ORTHODB_API_VERSION/data"}
    get_or_add_var "$ODBMAPPER_CONFIG" "MAP_ORTHODB_DATA" "$MAP_ORTHODB_DATA"
    if [[ -d "$MAP_ORTHODB_DATA" ]]; then
        DBI_DOWNLOAD="$ODBMAPPER_WORK/$URL_ORTHODB_API_VERSION/data/tarfiles"
        return 0
    fi

    if (( _IN_CONFIG == 1 )); then
        echo
        echo "ERROR: Found bad MAP_ORTHODB_DATA in $ODBMAPPER_CONFIG"
        echo "Set MAP_ORTHODB_DATA to a valid directory containing the orthologer software."
        echo
    else
        echo
        echo "ERROR: orthologer install dir is not readable: MAP_ORTHODB_DATA=$MAP_ORTHODB_DATA"
        echo "       Set it using 'export MAP_ORTHODB_DATA=<install dir>'"
        echo
    fi
    return 255
}

#------------------------------------------------------------
# Initialise base environment for given OrthoDB version.
#------------------------------------------------------------
init_base_env() {
    [[ $# -eq 1 ]] || return 255
    local odbver=$1
    local flevels="$ODBMAPPER_WORK/$odbver/etc/orthomapper_levels.sh"
    
    # check softlink here $flevels
    [[ -f "$flevels" ]] && return 0

    # check pipeline directory
    if [[ -d $DIR_ORTHOLOGER/etc ]]; then
        if [[ ! -d "$DIR_ORTHOLOGER/etc/$odbver" ]]; then
            echo
            echo "ERROR: orthologer installation does not seem to support the given OrthoDB version: $odbver"
            echo
            echo "The version specific directory is missing at"
            echo "    $DIR_ORTHOLOGER/etc/$odbver"
            echo
            echo "Is DIR_ORTHOLOGER correctly set?"
            echo
            return 255
        fi
        local f="$DIR_ORTHOLOGER/etc/$odbver/orthomapper_levels.sh"
        if [[ -f $f ]]; then
            ln -sf "$f" "$flevels"
        else
            echo
            echo "ERROR: Given orthologer installation root DIR_ORTHOLOGER=$DIR_ORTHOLOGER"
            echo "ERROR: does not seem to be correct - it's missing etc/${odbver}/orthomapper_levels.sh"
            echo
            return 255
        fi
    else
        echo
        echo "ERROR: DIR_ORTHOLOGER is not set to a valid directory!"
        echo
        return 255
    fi
    return 0
}

#-------------------------------------------------------
# Verify odbmapper work directory
#-------------------------------------------------------
#
# root config file - note this one is never fully read
# it is partially read/written in
#   set_orthologer_dir()
# and
#   set_map_orthodb_data()
#
ODBMAPPER_CONFIG="$ODBMAPPER_WORK/orthologer_conf.sh"

if [[ -n $ODBMAPPER_WORK ]]; then
    for odbver in ${ODB_VERSIONS[@]}; do
        if [[ ! -d "$ODBMAPPER_WORK/$odbver" ]]; then
            ###echo ">>> creating root environment at $ODBMAPPER_WORK/$odbver"
            create_base_env $odbver || exit 255
        fi
    done
else
    {
        echo
        echo "ERROR: ODBMAPPER_WORK must be set to a valid directory."
        echo "ODBMAPPER_WORK = $ODBMAPPER_WORK"
        echo "This directory will contain the structure to be used by orthologer for the mapping."
        echo
    } 1>&2
fi

#-------------------------------------------------------
# Determine orthologer install dir
#-------------------------------------------------------
#set_orthologer_dir || {
#    echo
#    echo "ERROR: Cannot determine orthologer install directory."
#    echo
#    echo "Consider setting it using"
#    echo "> export DIR_ORTHOLOGER=<orthologer install directory>"
#    echo
#    echo "Re-running ODB-mapper without arguments will then"
#    echo "save this version in the user configuration."
#    echo
#    exit 255
#} 1>&2

#-------------------------------------------------------
# set OrthoDB API
#-------------------------------------------------------
source $DIR_ORTHOLOGER/bin/set_orthodb_api.sh
set_orthodb_api || {
    echo "Failed setting OrthoDB version strings using URL_ORTHODB_API_VERSION=$URL_ORTHODB_API_VERSION ."
    echo "Reverting to 'current'."
    URL_ORTHODB_API_VERSION='current'
    set_orthodb_api || exit 255
}

#-------------------------------------------------------
# if no arguments just run orthomapper.sh
# -> generate quick help output
#-------------------------------------------------------
[[ $# -ge 1 ]] || {
    # no args - will print usage
    $DIR_ORTHOLOGER/bin/orthomapper.sh
    echo "By default the root work directory will be:"
    echo
    echo "> $ODBMAPPER_WORK"
    echo
    echo "It can be changed with:"
    echo "> export ODBMAPPER_WORK=<desired work directory>"
    echo
    exit 0
}

#-------------------------------------------------------
# init env for all valid versions
#-------------------------------------------------------
init_base_env "$URL_ORTHODB_API_VERSION" || exit 255

#-------------------------------------------------------
# set OrthoDB data directory
#-------------------------------------------------------
###set_map_orthodb_data || exit 255

#-------------------------------------------------------
# load levels
#-------------------------------------------------------
ORTHOMAPPER_LEVELS="$ODBMAPPER_WORK/$URL_ORTHODB_API_VERSION/etc/orthomapper_levels.sh"
if [[ ! -f "$ORTHOMAPPER_LEVELS" ]]; then
    ORTHOMAPPER_LEVELS="$DIR_ORTHOLOGER/etc/$URL_ORTHODB_API_VERSION/orthomapper_levels.sh"
fi
if [[ ! -f "$ORTHOMAPPER_LEVELS" ]]; then
    {
        echo
        echo "error: missing orthomapper_levels!"
        echo "Not found at"
        echo "   $ODBMAPPER_WORK/$URL_ORTHODB_API_VERSION/etc/"
        echo "or"
        echo "   $DIR_ORTHOLOGER/etc/$URL_ORTHODB_API_VERSION/orthomapper_levels.sh"
        echo
    } 1>&2
fi

#-------------------------------------------------------
# make sure environment is OK
#-------------------------------------------------------
verify_base_env "$URL_ORTHODB_API_VERSION" || exit 255

#-------------------------------------------------------
# Run orthomapper in version dependent directory
#-------------------------------------------------------
export DIR_PROJECT="$ODBMAPPER_WORK/$URL_ORTHODB_API_VERSION/pipeline"
export MAP_ORTHODB_DATA="$ODBMAPPER_WORK/$URL_ORTHODB_API_VERSION/data"
$DIR_ORTHOLOGER/bin/orthomapper.sh "$@"
