#!/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_PIPELINE_SH+1}" == "" ] && echo "ERROR $0 : main config has not been loaded" 1>&2 && exit 255
#------------------------------------------------

set -u
#---------------------------------------------------------------------------
# get args
[[ $# -eq 4 ]] || fatal_msg "usage: $0 <[[rootBRH or fpairs] or [childOg1,childBRH1,childOg2,...,fpairs]> <Output OGs> <weakbrh> <nthreads>"

arginpf="$1"   # input file(s)
output="$2"    # output cluster file
weakbrh="$3"   # output weak BRH's - optional, if '-' then it's not evaluated
nthreads="$4"

# check if weakbrh="-"
[[ "$weakbrh" == "-" ]] && weakbrh=""

# check input file(s) argument
inpfiles=( $(tokenize "," $arginpf) )
nfiles=${#inpfiles[@]}

# nr of files
(( nfiles>0 )) || fatal_msg "no input files given!"

# check nr of kids
nkids=0
(( nfiles>1 )) && nkids=$(((nfiles-1)/2))

#---------------------------------------------------------------------------
# get BRH or pairs file
fbrhsel="${inpfiles[-1]}"
info_msg "-> got BRH input spec file: $fbrhsel"
info_msg "clustering runs with seeds"
nodelbl=$(file_basename $fbrhsel)

#---------------------------------------------------------------------------
# check input files
for (( i=0; i<nfiles; i++ )); do
    check_file "$0" "${inpfiles[$i]}" || exit 255
done



#---------------------------------------------------------------------------
# set brhclus options

isset "OPTS_BRHCLUS" || OPTS_BRHCLUS=

optthreads=""
opts=""
# options specifiying BRH sources (for brhclus and extractpairs)
inpbrh=""
# options specifying input clusters
inpcls=""
# optional index
inpind=""
# brhclus output
optout=""

[[ $nthreads -gt 1 ]] && optthreads="-T $nthreads"
opts="--trieval $BRHCLUS_TRIEVAL --paireval $BRHCLUS_PAIREVAL -r $BRHCLUS_MAX_SPRATIO --overlap $MIN_OVERLAP --mincov $MIN_COVERAGE $optthreads --reqlinks $BRHCLUS_MERGE_FNLINKS"

# get input pairs
if (( nkids == 0 )); then
    # no kids
    inpbrh="-P $(trim_name $fbrhsel)"
else
    # kids:
    # - weak BRHs for each kid
    # - species pairs file
    # - PWC dir
    # - cluster file for each kid
    #
    for (( i=0; i<nkids; i++ )); do
        j=$((2*i))
        inpcls="$inpcls -C $(trim_name ${inpfiles[$j]})"
        inpbrh="$inpbrh -P $(trim_name ${inpfiles[$((j+1))]})"
    done
    inpbrh="$inpbrh -P $(trim_name $fbrhsel)"
fi

# add PWC source which is used if fbrhsel is a pairs file
inppwc="--pwc $(trim_name $DIR_PROJECT_PWC)"

# output cluster file
optout="-g $(trim_name $output)"

# look for index file
indexfile="Cluster/${nodelbl}.index"
if [[ ! -f "$indexfile" ]]; then
    indexfile=""
    if [[ $TREE_ENABLED == "1" ]]; then
        if [[ -n $TREE_ROOT_CLADE ]]; then
            indexfile="Cluster/${TREE_ROOT_CLADE}.index"
            [[ -f $indexfile ]] || indexfile=""
        fi
    fi
fi

if [[ -n "$indexfile" ]]; then
    inpind="-i $indexfile"
    info_msg "using index file $indexfile"
else
    info_msg "no index file found for label $nodelbl - this is OK"
fi

#---------------------------------------------------------------------------
# check if brhclus has dumpweak
weakopts=""
tmpweak=""
tmpweakopts=""
tmpwbrh=""
if [[ -n "$weakbrh" ]]; then
    tmpwbrh=""
    tmp_make tmpwbrh "weakbrh" || exit 255
    info_msg "dump weak BRHs directly through brhclus to file $(trim_name $weakbrh)"
    weakopts="--dumpweak --outbrh $(trim_name $weakbrh)"
    tmpweakopts="--dumpweak --outbrh $tmpwbrh"
fi

#---------------------------------------------------------------------------
# ready to run the clustering
cmdWithOpts="$EXE_BRHCLUS $opts $OPTS_BRHCLUS $inpbrh $inppwc $inpcls $inpind $optout $weakopts"
info_msg "starting clustering"
info_msg "cmd: $cmdWithOpts"


# use temp files for output
tmpogs=""
tmp_make tmpogs "cluster" || exit 255
tmplog="${tmpogs}.log"
tmp_add_file $tmplog
# go
startdate=$(date)
tA=$(time_nsec)
ec=0
allopts="$opts $OPTS_BRHCLUS $inpbrh $inppwc $inpcls $inpind -g $tmpogs $tmpweakopts"
if (( BRHCLUS_USE_HUGEMEM == 0 )); then
    "$EXE_BRHCLUS" $allopts > $tmplog 
    ec=$?
else
    if [[ -f $LIB_HUGEMEM ]]; then
        info_msg "using HUGEMEM with library $LIB_HUGEMEM"
        LD_PRELOAD=$LIB_HUGEMEM HUGETLB_MORECORE=yes "$EXE_BRHCLUS" $allopts > $tmplog
        ec=$?
    else
        warn_msg "HUGEMEM was requested but library is missing at: $LIB_HUGEMEM"
        warn_msg "running without HUGEMEM enabled"
        "$EXE_BRHCLUS" $allopts > $tmplog
        ec=$?
    fi
fi

if [[ $ec -ne 0 ]]; then
    error_msg "$0: failed brhclus with options $allopts"
    echoerr "#LOG file:"
    cat ${tmplog} 1>&2
    echoerr "#OGS file:"
    cp -vf $tmpogs /tmp/clusters_save.og
    exit 255
fi
dT=$(delta_time $tA)

# add header and footer and fix access mode
add_header_footer $0 $tmpogs "$output" "$startdate" "$dT" "$cmdWithOpts"
if [[ $? -ne 0 ]]; then
	echoerr "# Output: "
	cat $tmpogs 1>&2
    echoerr "#LOG file:"
    cat ${tmpogs}.log 1>&2
    exit 255
fi
# copy log file
cp -f $tmplog ${output}.log

chmod 644 "$output"
chmod 644 "${output}.log"


if [[ -n "$weakbrh" ]]; then
    {
        print_header "$cmdWithOpts" "$startdate"
        sort "$tmpwbrh"
        print_footer "$dT"
    } >& "$weakbrh"
    if [[ $? -ne 0 ]]; then
	    echoerr "# Output: "
	    cat $tmpwbrh 1>&2
        exit 255
    fi
    chmod 644 "$weakbrh"
    info_msg "done weakbrh -> $weakbrh"
fi


info_msg "done clustering -> $output"

# DONE
