#!/usr/bin/env bash
#
# orthologer - Pipeline for deducing orthology from fasta files.
# Copyright (C) 2005-2023 E. Zdobnov lab: F. Tegenfeldt
# <fredrik.tegenfeldt@unige.ch> based on code by E. Kriventseva
#
# This file is part of orthologer.
#
# orthologer is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# orthologer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with orthologer.  If not, see <http://www.gnu.org/licenses/>.
#
#--- check if environment is ok -----------------
[[ "${LOADED_COMMON_ORTHODB_SH+1}" == "" ]] && echo "ERROR $0 : main common_odb.sh has not been loaded" 1>&2 && exit 255
#------------------------------------------------

_VARDEF_NWARN=0
_VARDEF=""
deprecate_var() {
    local varname="$1"
    if isset_var "$varname"; then
        _VARDEF_NWARN=$((_VARDEF_NWARN+1))
        warn_msg "Variable $varname is deprecated"
    fi
}

deprecate_assoc() {
    local varname="$1"
    if isset_assoc "$varname"; then
        _VARDEF_NWARN=$((_VARDEF_NWARN+1))
        warn_msg "Variable $varname is deprecated"
    fi
}

add_var() {
    local varname=$1
    local defval="$2"
    _VARDEF=""
    if ! isset_var "$varname"; then
        _VARDEF_NWARN=$((_VARDEF_NWARN+1))
        warn_msg "Variable $varname is missing - setting to default value <$defval>"
        _VARDEF="export $varname=\"$defval\""
        return 1
    fi
    return 0
}

rename_var() {
    local oldvar="$1"
    local newvar="$2"
    _VARDEF=""
    debug_msg "rename $oldvar to $newvar"
    if isset_var "$oldvar"; then
        _VARDEF_NWARN=$((_VARDEF_NWARN+1))
        warn_msg "rename $oldvar to $newvar"
        #if isset_var "$newvar"; then
        #    warn_msg "Old ($oldvar) and new ($newvar) variables exists - set $newvar = $oldvar"
        #    warn_msg "Old setting $newvar=${!oldvar}"
        #else
        #    warn_msg "Variable $oldvar exists - replaced with new variable $newvar"
        #fi
        _VARDEF="export $newvar=\"${!oldvar}\" ; unset $oldvar"
        return 1
    fi
    return 0    
}

rename_assoc() {
    local oldvar="$1"
    local newvar="$2"
    _VARDEF=""
    if isset_assoc "$oldvar"; then
        _VARDEF_NWARN=$((_VARDEF_NWARN+1))
        warn_msg "Associative variable $oldvar exists - replace with new variable $newvar"
        _VARDEF="declare -A $newvar=$(declare -p $oldvar | cut -d "=" -f 2-)"
        return 1
    fi
    return 0    
}

new_default() {
    local varname=$1
    local defval="$2"
    defval=${defval^^}
    
    _VARDEF=""
    if ! isset_var "$varname"; then
        _VARDEF_NWARN=$((_VARDEF_NWARN+1))
        warn_msg "Variable $varname is missing - setting to default value <$defval>"
        _VARDEF="export $varname=\"$defval\""
        return 1
    else
        local old="${!varname}"
        old=${old^^}
        if [[ "$old" != "$defval" ]]; then
            warn_msg "Variable $varname is not set to recomended value = $defval"
            warn_msg "Variable $varname is set to ${!varname}"
            _VARDEF_NWARN=$((_VARDEF_NWARN+1))
        fi
    fi
    return 0
}

new_proj_dir() {
    local varname=$1
    local defval="$2"
    _VARDEF=""
    if ! isset_var "$varname"; then
        _VARDEF_NWARN=$((_VARDEF_NWARN+1))
        warn_msg "Directory variable $varname is missing - setting to default value <$defval>"
        _VARDEF="export $varname=\"$defval\""
        return 1
    fi
    return 0
}

rename_file() {
    local fold=$1
    local fnew=$2
    if [[ -f $fnew ]]; then
        if [[ -f $fold ]]; then
            _VARDEF_NWARN=$((_VARDEF_NWARN+1))
            warn_msg "both old ($fold) and new ($fnew) files exists"
            warn_msg "the old file will be ignored"
        fi
    else
        warn_msg "obsolete file exists at $fold"
        warn_msg "will softlink to $fnew"
        ln -sf "$fold" "$fnew"
        _VARDEF_NWARN=$((_VARDEF_NWARN+1))
    fi
}

_DIAMOND_VERSION=""
check_diamond_version() {
    _DIAMOND_VERSION=""
    local vmain=$1
    local vsub=$2
    local vmin=$3
    
    [[ -x $DIR_DIAMOND/diamond ]] || return 255
    _DIAMOND_VERSION="$($DIR_DIAMOND/diamond --version | cut -d ' ' -f 3)"
    [[ $? -eq 0 ]] || {
        error_msg "unable to call diamond --version"
        return 255;
    }
    local v=( $(echo $_DIAMOND_VERSION | tr '.' ' ') )
    [[ ${#v[@]} -eq 3 ]] || {
        error_msg "strange diamond version <$_DIAMOND_VERSION>"
        return 255;
    }
    [[ ${v[0]} -lt $vmain ]] && return 1
    [[ ${v[1]} -lt $vsub  ]] && return 2
    [[ ${v[2]} -lt $vmin  ]] && return 3
    return 0
}

validate_diamond_version() {
    [[ $ALIGNMENT_LABEL == "DIAMOND" ]] || return 0
    
    local vmain=$1
    local vsub=0
    local vmin=0
    [[ $# -ge 2 ]] && vsub=$2
    [[ $# -ge 3 ]] && vmin=$3
    [[ -x $DIR_DIAMOND/diamond ]] || {
        return 0
    }
    local ec=0
    check_diamond_version "$vmain" "$vsub" "$vmin"
    ec=$?
    (( ec == 0 )) && return 0
    _VARDEF_NWARN=$((_VARDEF_NWARN+1))
    (( ec == 255 )) && {
        error_msg "error determining diamond version"
        return 255
    }
    error_msg "bad diamond version $_DIAMOND_VERSION < ${vmain}.${vsub}.${vmin}"
    return $ec
}

#----------------------------------------------------------
# change 17/06/2015
# This particular one should never be a problem as COMPRESS_DATA is defined in common_pipeline.sh
# Keep it in order to capture odd situations (?)
# change 16/7/2021 - removal of compression support
##add_var COMPRESS_DATA 1 || eval "$_VARDEF"

#----------------------------------------------------------
# change 16/06/2015
rename_var OPTS_NUMALIGNMENTS ALIGNER_NUMALIGNMENTS || eval "$_VARDEF"
rename_var OPTS_EFFDBSZ       ALIGNER_EFFDBSZ       || eval "$_VARDEF"
    
#----------------------------------------------------------
# change 25/04/2016
rename_var ALIGNER_LABEL          ALIGNMENT_LABEL           || eval "$_VARDEF"
rename_var ALIGNER_MATRIX         ALIGNMENT_MATRIX          || eval "$_VARDEF"
rename_var ALIGNER_MAXEVAL_SCALE  ALIGNMENT_MAXEVAL_SCALE   || eval "$_VARDEF"
rename_var ALIGNER_NUMALIGNMENTS  ALIGNMENT_NUMALIGNMENTS   || eval "$_VARDEF"
rename_var ALIGNER_EFFDBSZ        ALIGNMENT_EFFDBSZ         || eval "$_VARDEF"

#----------------------------------------------------------
# change 19/02/2020
# renaming
rename_var SET_IGNORE_MISSING     IGNORE_MISSING || eval "$_VARDEF"

#----------------------------------------------------------
# change 30/04/2020
# renaming
rename_var TREE_ORTHODB_URL       TREE_INPUT_ODB || eval "$_VARDEF"
rename_var TREE_ENABLE            TREE_ENABLED   || eval "$_VARDEF"

#----------------------------------------------------------
# change 18/08/2020
rename_var USE_MMSEQS_SEARCH MMSEQS_MODE  || eval "$_VARDEF"

#----------------------------------------------------------
# change 20/08/2020
rename_var MMSEQS_MODE MMSEQS_ALIGN_MODE  || eval "$_VARDEF"
add_var    ODB_RUN_MODE DEFAULT  || eval "$_VARDEF"

#----------------------------------------------------------
# add variables
add_var BRHCLUS_MAX_SPRATIO 0.5 || eval "$_VARDEF"
add_var TREE_INPUT_FILE ""      || eval "$_VARDEF"



#----------------------------------------------------------
# deprecated vars
deprecate_var DIR_PARALIGN
deprecate_var LIC_PARALIGN
deprecate_var ALIGNMENT_EFFDBSZ
deprecate_var ALIGNMENT_MAXEVAL_SCALE
deprecate_var ALIGNMENT_MAXEVAL

# related to old blast
deprecate_var EXE_FORMATDB
deprecate_var EXE_BLASTALL
deprecate_var EXE_BLASTCLUST

# wublast
deprecate_var DIR_WUBLAST

# mergeinpar
deprecate_var MERGEINPAR_CLFUNC

# brhclus
deprecate_var BRHCLUS_MINCONN
deprecate_var BRHCLUS_MINLINK

#----------------------------------------------------------
# change 16/06/2020
# renaming
rename_var OP_POSTPROC_SCRIPT       POSTPROC_LABEL || eval "$_VARDEF"

#----------------------------------------------------------
# change 3/9/2020
# related to fuzzy BRH's
add_var MAKEBRH_NALT       1     || eval "$_VARDEF"
add_var MAKEBRH_FSEPMAX    0.05  || eval "$_VARDEF"

#----------------------------------------------------------
# change 7/9/2020
# changed values of ODB_RUN_MODE
if [[ "$ODB_RUN_MODE" == "0" ]]; then
    info_msg "ODB_RUN_MODE: value 0 changed to DEFAULT"
    ODB_RUN_MODE="DEFAULT"
elif [[ "$ODB_RUN_MODE" == "1" ]]; then
    info_msg "ODB_RUN_MODE: value 1 changed to FAST"
    ODB_RUN_MODE="FAST"
elif [[ "$ODB_RUN_MODE" == "2" ]]; then
    info_msg "ODB_RUN_MODE: value 2 changed to FAST"
    ODB_RUN_MODE="FAST"
elif [[ "$ODB_RUN_MODE" == "3" ]]; then
    info_msg "ODB_RUN_MODE: value 3 changed to SENSITIVE"
    ODB_RUN_MODE="SENSITIVE"
elif [[ "$ODB_RUN_MODE" == "10" ]]; then
    info_msg "ODB_RUN_MODE: value $ODB_RUN_MODE changed to USER"
    ODB_RUN_MODE="USER"
fi

#----------------------------------------------------------
# change 1/10/2020
# rename variable
rename_var BRHCLUS_MINCOV    MIN_COVERAGE   || eval "$_VARDEF"

# rename BLASTPLUS to BLAST
rename_var DIR_BLASTPLUS     DIR_BLAST   || eval "$_VARDEF"
rename_var OPTS_BLASTPLUS    OPTS_BLAST  || eval "$_VARDEF"

rename_var MMSEQS_SCORE_MODE ALIGNMENT_SCORE_MODE  || eval "$_VARDEF"

#----------------------------------------------------------
# change 24/10/2020
add_var BRHCLUS_MERGE_FNLINKS   0.6     || eval "$_VARDEF"

#----------------------------------------------------------
# change 18/01/2021
###add_var TREE_PWC_RUN 0 || eval "$_VARDEF"

#----------------------------------------------------------
# change 23/02/2021
rename_var TREE_PWC_RUN TREE_CLUSTER_RUN || eval "$_VARDEF"

#----------------------------------------------------------
# remove SPLITBRH from assoc arrays
[[ ${OP_STEP_NPARALLEL[SPLITBRH]+abs} ]] && {
    info_msg "removing SPLITBRH from OP_STEP variables"
    unset OP_STEP_NPARALLEL[SPLITBRH]
    unset OP_STEP_NTHREADS[SPLITBRH]
    unset OP_STEP_NMERGE[SPLITBRH]
    unset OP_STEP_ENABLE[SPLITBRH]
    unset OP_STEP_RUNMODE[SPLITBRH]
#    unset OP_STEP_COMPRESS[SPLITBRH]
    unset OP_STEP_SCHEDOPTS[SPLITBRH]
}
#----------------------------------------------------------
# warn if COMPRESS_DATA is set
#if (( COMPRESS_DATA != 0 )); then
#    # the reason for this is to speed up the alignment computation as much as possible
#    warn_msg "COMPRESS_DATA is set -> note that compression is currently disabled in alignment/makebrh/makeinpar steps"
#    OP_STEP_COMPRESS[ALIGNMENT]=0
#    OP_STEP_COMPRESS[MAKEBRH]=0
#    OP_STEP_COMPRESS[MAKEINPAR]=0
#    _VARDEF_NWARN=$((_VARDEF_NWARN+1))
#fi

#----------------------------------------------------------
# test if allowpoor is set in OPTS_MERGEINPAR
tstOPTS_MERGEINPAR="${OPTS_MERGEINPAR//--allowpoor/}"
if [[ $tstOPTS_MERGEINPAR != $OPTS_MERGEINPAR ]]; then
    OPTS_MERGEINPAR="$tstOPTS_MERGEINPAR"
    warn_msg "removed obsolete option --allowpoor from OPTS_MERGEINPAR"
fi

#----------------------------------------------------------
# special msg related to MMSEQS
if (( ALIGNMENT_SCORE_MODE == 1 )); then
    fatal_msg "deprecated ALIGNMENT_SCORE_MODE=$ALIGNMENT_SCORE_MODE - change to recommended value of 2"
fi

#----------------------------------------------------------
# warn if not recommended aligner
# updated 2/2/2023 to DIAMOND
if [[ $ALIGNMENT_LABEL != DIAMOND ]]; then
    warn_msg "Using alignment by $ALIGNMENT_LABEL and not the recommended DIAMOND."
    ####warn_msg "This means the sensitivity parameter MMSEQS_SENSITIVITY has no effect."
fi

#----------------------------------------------------------
# removed compression
deprecate_var COMPRESS_DATA
[[ ${OP_STEP_COMPRESS[MAKEBRH]+abs} ]] && { _VARDEF_NWARN=$((_VARDEF_NWARN+1)); warn_msg "OP_STEP_COMPRESS is deprecated"; }

#----------------------------------------------------------
# removed DIR_ORTHOPIPE (7/7/2022)
deprecate_var DIR_ORTHOPIPE

#----------------------------------------------------------
# change 26/8/2022
add_var PL_TODO_ONE2ONE   0     || eval "$_VARDEF"

#----------------------------------------------------------
# change 3/10/2022
# Remove NUCL support (it was anyway deprecated)
deprecate_var DATA_TYPE

#----------------------------------------------------------
# change 7/12/2022, updated 20/12/2022 (v11 -> current)
# change 3/9/2024, URL_ORTHODB_API no longer set by user
#                  API url is given in two parts
###add_var URL_ORTHODB_API "https://data.orthodb.org/current" || eval "$_VARDEF"
###new_default URL_ORTHODB_API ""                             || eval "$_VARDEF"
add_var URL_ORTHODB_API_BASE    "https://data.orthodb.org" || eval "$_VARDEF"
add_var URL_ORTHODB_API_VERSION "current"                  || eval "$_VARDEF"

#----------------------------------------------------------
# change default aligner from mmseqs to diamond
# january 2023
new_default ALIGNMENT_LABEL "DIAMOND"

#----------------------------------------------------------
# change 8/2/2023 - orthologer config file name
rename_file common.sh orthologer_conf.sh

#----------------------------------------------------------
# check diamond version (if ALIGNMENT_LABEL == diamond)
validate_diamond_version 2 1 0

#----------------------------------------------------------
# change 07/11/2023
rename_var OP_LABELA_START OP_LABELA_FIRST || eval "$_VARDEF"
rename_var OP_LABELA_END   OP_LABELA_LAST  || eval "$_VARDEF"
rename_var OP_LABELB_START OP_LABELB_FIRST || eval "$_VARDEF"
rename_var OP_LABELB_END   OP_LABELB_LAST  || eval "$_VARDEF"

#----------------------------------------------------------
# change 7/9/2024
rename_var DIR_PIPELINE   DIR_ORTHOLOGER  || eval "$_VARDEF"

#----------------------------------------------------------
# merge pairs have a temp fix for OrthoDB bacteria run 2020
# NOT NEEDED ANYMORE - brhclus etc reads directly from pairwise
###warn_msg "* Temporary fix for SETBRH (merge_by_pairs_nochecks())."
###warn_msg "  -> removes all fuzzy BRHs in order to reduce file sizes."

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if [[ $_VARDEF_NWARN -gt 0 ]]; then
    warn_msg "found $_VARDEF_NWARN warnings - fix your orthologer_conf.sh"
    warn_msg "> ./orthologer.sh -u${COLOR_RESET}"
fi
