#!/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/>.
#

# make sure local common.sh file exists
[ -x common.sh ] || { echo "error: no local common.sh found" 1>&2; exit 255; }
source common.sh

STATUS_STEPS=""
SHOW_EMPTY=0
SHOW_MISSING=0
SHOW_SUMMARY=0

process_args() {
    OPTIND=1
    local opts=":t:s:MLESph"
    while getopts $opts OPT; do
        case "$OPT" in
            h)  echo "./status.sh -s <step(s)> [-t <todo file> -d -L -S]"
                echo "  -d               : dry run - don\'t do anything"
                echo "  -t <todo file>   : todo file to use"
                echo "  -s <steps>       : select which steps to archive"
                echo "  -L               : ignore OP_LABELX_START/END for pairwise"
                echo "  -M               : show only labels with missing (pairwise)"
                echo "  -E               : also show empty labels (pairwise)"
                echo "  -S               : only show summary (pairwise)"
                echo "  -p               : pretty print"
                echo "  -h               : this message"
                exit 0
                ;;
            p)  PRETTY_PRINT=1
                reset_attributes
                ;;
            t)  PL_TODO="$OPTARG"
                ;;
            s)  STATUS_STEPS="$OPTARG"
                STATUS_STEPS=${STATUS_STEPS^^}
                ;;
            L)  OP_LABELA_FIRST=""
                OP_LABELA_LAST=""
                OP_LABELB_FIRST=""
                OP_LABELB_LAST=""
                ;;
            M)  SHOW_MISSING=1
                ;;
            E)  SHOW_EMPTY=1
                ;;
            S)  SHOW_SUMMARY=1
                SHOW_EMPTY=0
                SHOW_MISSING=0
                ;;
            *)  error_msg "unknown option ($OPTARG)"
                return 255
                ;;
        esac
    done

    # steps is required
    [[ -n $STATUS_STEPS ]] || { error_msg "missing required option -s <step(s)>"; return 255; }

    setup_environment
    
    expand_step_list $STATUS_STEPS
    STATUS_STEPS="${STEP_ID_LIST[@]}"
    [ $? -eq 0 ] || { error_msg "failed expanding step list $STATUS_STEPS"; return 255; }
    return 0
}

status_label() {
    [ $# -ge 2 ] || return 255
    local dir="$1"
    shift
    local extensions="$*"

    [[ -d $dir ]] || return 255
    # loop over all todo labels
    local T=""
    local nok=0
    local nbad=0
    for T in "${PL_TODO_LABELS[@]}"; do
        # check label
        isok_label "A" $T || continue
        for ext in $extensions; do
            local f="$dir/${T}.$ext"
            if [[ -f $f ]]; then
                nok=$((nok+1))
            else
                nbad=$((nbad+1))
            fi
        done
    done
}

status_pairwise() {
    [ $# -eq 2 ] || return 255
    local extension="$1"
    local matrix=$2

    local i=0
    local N=${#PL_TODO_LABELS[@]}
    local T=""
    local nokall=0
    local ntotall=0
    local noklbl=0
    local npartlbl=0
    local nempty=0

    CHECK_COUNTER=0

    local NB=$N
    case $matrix in
        0)  dNB=0  # full matrix
            ;;
        1)  dNB=1  # half-matrix, including diagonal
            NB=$((N+1))
            ;;
        2)  dNB=1  # half-matrix, excluding diagonal
            ;;
        3)  dNB=0  # full matrix, excluding diagonal
            NB=$((N-1))
            ;;
        *)  error_msg "invalid matrix type <$matrix>"
            return 255
            ;;
    esac

    # loop over all todo labels
    for T in "${PL_TODO_LABELS[@]}"; do

        # update nr of expected B
        NB=$((NB-dNB))
        [ $NB -gt 0 ] || break

        # check label
        isok_label "A" $T || continue
        ntotall=$((ntotall+NB))

        # PWC directory - get this from function!!!
        local pwcdir="PWC/$T"
        [[ -d $pwcdir ]] || continue

        # get nr of files
        local nfiles=$(find $pwcdir/ -maxdepth 1 -name '*.'$extension | wc -l)
        if [[ $nfiles -eq $NB ]]; then
            noklbl=$((noklbl+1))
        elif [[ $nfiles -gt 0 ]]; then
            npartlbl=$((npartlbl+1))
        else
            nempty=$((nempty+1))
        fi

        nokall=$((nokall+nfiles))

        [[ $SHOW_SUMMARY -eq 1 ]] && continue
        [[ $SHOW_MISSING -eq 1 && $nfiles -eq $NB ]] && continue
        [[ $SHOW_EMPTY -eq 0 && $nfiles -eq 0 ]] && continue

        # print nr of files
        msg="${FACE_BOLD}$STEP_ID ${T}${FACE_NORMAL}"
        num_status_msg "$msg" $NB $nfiles
    done

    printf "%-20s %-20s : %s\n" $STEP_ID "N(done)" "$noklbl"
    printf "%-20s %-20s : %s\n" $STEP_ID "N(partial)" "$npartlbl"
    printf "%-20s %-20s : %s\n" $STEP_ID "N(remaining)" "$nempty"
#    cnt_sum_msg
#
#    msg="${FACE_BOLD}${STEP_ID}${FACE_NORMAL}"
#    num_status_msg "$msg" $ntotall $nokall
}

status_alignment() {
    status_pairwise $EXT_ALIGN 0
}

#status_alignbest() {
#    status_pairwise $EXT_ALIGNBEST 3
#}

# check if pipeline is running and if any jobs are running
status() {
    local ec=0
    print_separator
    # get running pid
    # cleanup stale file
    cleanup_pid_file
    get_pid
    local pid=$R_PID
    [ $pid -gt 0 ] || pid="<not running>"

    printf "%-20s : %s\n" "Job PID" "$pid"
    printf "%-20s : %s - %s\n" "LABEL A" "$OP_LABELA_FIRST" "$OP_LABELA_LAST"
    # check for jobs
    # first update jobid file
    local step=""
    for step in $STATUS_STEPS; do
        update_jobid_file $step
        # temp fix of an old bug
        local njobs=( $(get_njobs $step) )
        [ ${njobs[0]} -gt 0 ] || continue
        printf "%-20s : %s job(s)\n" "$step" "${njobs[0]}"
    done
    print_separator
}


process_args $*

status

for step in $STATUS_STEPS; do
    func=status_${step,,}
    isfunc $func || { warn_msg "No function <$func> defined!"; continue; }
    set_stepid $step
    $func
done

