#!/bin/bash

export LANG=en_US.UTF-8

# NOTE: A linha imediatemente acima evita problemas de compatibilidade com o
# UTF-8! By Questor
# NOTE: Trata-se de um utilitário p/ usar o "pserve" como um serviço padrão. 
# Embora, "pserve" não seja indicado para produção optamos por "pserve" pq os 
# comandos recebidos pelo LBC são os mínimos possíveis. Perceba ainda que o
# controle desse serviço é todo "stand alone" (PID e tudo o mais). Isso é útil 
# para termos vários serviços funcionando de forma independente e em portas 
# diferentes! Esse utilitário tb facilita o controle do LBConverter oferecendo 
# uma nova "cara" p/ o mesmo. Até então a implementação atual do esquema em 
# pauta é provisória! By Questor

# Note: Obtêm o caminho do arquivo "lbindexmg" para que as chamadas sejam 
# feitas no lugar correto! By Questor
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# Note: Informar o caminho python2 onde o LBIndex está instalado! By Questor
PYTHON2="<VIRTUALENV_PATH>"

# NOTE: Para o serviço pserve (e o LBI na sequência)! By Questor
stop_services() {
    printf "Stopping http service:"
    get_pserve_status
    if [ "$GET_PSERVE_STATUS_RTN" != "" ]; then

        # NOTE: Usamos "&" como uma manobra p/ não printar a saída em certos 
        # casos! By Questor
        kill -9 "$GET_PSERVE_STATUS_RTN" &
        rm -f /var/run/lbihttp.pid
        echo "                                      [  OK  ]"
        f_set_exit_code 0
    else
        echo "                                      [FAILED]"
        f_set_exit_code 0
    fi

    # NOTE: Nos casos onde o comando "start" falha p/ a parte do LBI, não se 
    # faz necessário tentar para-lo já que ele não está rodando! By Questor
    if [ "$1" != "only_pserve" ]; then
        stop_lbi
    fi
}

# NOTE: Inicia o serviço pserve (e o LBI na sequência). O comando "jobs" evita 
# que o script fique presso na linha de execução! By Questor
start_services() {
    echo "Starting services..."
    get_pserve_status
    if [ "$GET_PSERVE_STATUS_RTN" == "" ]; then
        printf "Starting http service:"
        rm -f pserveout
        jobs &>/dev/null
        eval "$PYTHON2/bin/pserve $SCRIPTDIR/production.ini >pserveout 2>&1 &"
        PSERVE_EXIT_CODE_R=$?
        new_job_started="$(jobs -n)"
        if [ -n "$new_job_started" ]; then
            PID=$!
        else
            PID=
        fi

        # NOTE: Como a saída p/ "pserveout" é assíncrona usamos um sleep de 1 
        # segundo (pode haver dessincronia)! By Questor
        sleep 1

        PSERVEOUT=$(<pserveout)
        rm -f pserveout

        if [[ $PSERVEOUT != "" ]]; then
            echo "                                      [FAILED]"
            echo "$PSERVEOUT"
            f_set_exit_code $PSERVE_EXIT_CODE_R
        else
            printf "$PID" > /var/run/lbihttp.pid
            echo "                                      [  OK  ]"
            f_set_exit_code 0
            start_lbi
        fi
    fi
}

# NOTE: Printa o status do serviço pserve (e do LBI na sequência)! By Questor
status_services() {
    get_pserve_status
    if [ "$GET_PSERVE_STATUS_RTN" == "" ]; then
        echo "http service is stopped"
    else
        echo "http service (pid  $GET_PSERVE_STATUS_RTN) is running..."
    fi
    status_lbi
}

# NOTE: Reinicia o serviço pserve (e o LBI na sequência)! By Questor
restart_services() {
    stop_services
    start_services
}

# NOTE: Exibe a ajuda do LBI! By Questor
help_services() {
    f_get_stderr_stdout "cd $SCRIPTDIR && $PYTHON2/bin/python lbindex help"
    if [[ $F_GET_STDERR_R != "" ]]; then
        echo "                                             [FAILED]"
        echo "$F_GET_STDOUT_R$F_GET_STDERR_R"
        f_set_exit_code $F_GET_EXIT_CODE_R
    else
        echo "$F_GET_STDOUT_R"
        f_set_exit_code $F_GET_EXIT_CODE_R
    fi
}

# NOTE: Obtêm o arquivo "PID" ("lbihttp.pid") criado por "pservemg" para 
# controle do processo do "pserve"! Se o "PID" atual não for mais válido 
# deleta o "lbihttp.pid"! By Questor
GET_PSERVE_STATUS_RTN=""
get_pserve_status() {
    GET_PSERVE_STATUS_RTN=""
    if [ -f /var/run/lbihttp.pid ]; then
        PSERVEPIDVAL=$(</var/run/lbihttp.pid)
        if ps -p $PSERVEPIDVAL > /dev/null
        then
           GET_PSERVE_STATUS_RTN="$PSERVEPIDVAL"
        else
           rm -f /var/run/lbihttp.pid
        fi
    fi
    f_set_exit_code 0
}

F_GET_STDERR_R=""
F_GET_STDOUT_R=""
F_GET_EXIT_CODE_R=0
f_get_stderr_stdout() {
    : 'Executar um comando e colocar a saída de stderr e stdout nas 
    variáveis "F_GET_STDERR_R" e "F_GET_STDOUT_R"!.

    Args:
        CMD_TO_EXEC (str): Comando a ser executado.

    Returns:
        F_GET_STDERR_R (str): Saída para stderr.
        F_GET_STDOUT_R (str): Saída para stdout.
        F_GET_EXIT_CODE_R (int): Saída do exit code.
    '

    CMD_TO_EXEC=$1
    F_GET_STDERR_R=""
    F_GET_STDOUT_R=""
    F_GET_EXIT_CODE_R=0
    unset t_std t_err t_ret
    eval "$( eval "$CMD_TO_EXEC" 2> >(t_err=$(cat); typeset -p t_err) > >(t_std=$(cat); typeset -p t_std); t_ret=$?; typeset -p t_ret )"
    F_GET_EXIT_CODE_R=$t_ret
    F_GET_STDERR_R=$t_err
    F_GET_STDOUT_R=$t_std
}

F_SET_EXIT_CODE_R=0
f_set_exit_code() {
    : 'Permite setar um código de saída ("exit code") geral para a 
    execução atual.

    Esse código só pode ser setado UMA VEZ e isso ocorre sempre quando 
    o código for DIFERENTE DE 0 (sucesso).

    Args:
        EXIT_CODE_P (Optional[int]): Códido a ser setado. Se vazio o 
    padrão será 0.

    Returns:
        F_SET_EXIT_CODE_R (int): Código na chamada da função.
    '

    EXIT_CODE_P=$1
    if [ -z "$EXIT_CODE_P" ] ; then
        EXIT_CODE_P=0
    fi

    if [ ${F_SET_EXIT_CODE_R} -eq 0 ] ; then
        F_SET_EXIT_CODE_R=$EXIT_CODE_P
    fi
}

# NOTE: Obtêm o status do serviço LBI retornando 1 para rodando e 0 para 
# parado! By Questor
GET_LBI_STATUS_RTN=""
get_lbi_status() {
    GET_LBI_STATUS_RTN=""
    f_get_stderr_stdout "cd $SCRIPTDIR && $PYTHON2/bin/python lbindex status"
    if [[ $F_GET_STDOUT_R = *"is running"* ]]; then
        GET_LBI_STATUS_RTN=1
        f_set_exit_code $F_GET_EXIT_CODE_R
    else
        GET_LBI_STATUS_RTN=0
        f_set_exit_code $F_GET_EXIT_CODE_R
    fi
}

# NOTE: Para o serviço LBI! By Questor
stop_lbi() {
    printf "Stopping lbindex:"
    get_lbi_status
    if [ ${GET_LBI_STATUS_RTN} -eq 1 ]; then
        f_get_stderr_stdout "cd $SCRIPTDIR && $PYTHON2/bin/python lbindex stop"
        if [[ $F_GET_STDERR_R != *"Daemon not running"* ]]; then
            echo "                                           [  OK  ]"
            f_set_exit_code $F_GET_EXIT_CODE_R
        else
            echo "                                           [FAILED]"
            f_set_exit_code $F_GET_EXIT_CODE_R
        fi
    else
        echo "                                           [FAILED]"
    fi
}

# NOTE: Inicia o serviço LBI. O comando "jobs" evita que o script fique 
# presso na linha de execução! By Questor
start_lbi() {
    printf "Starting lbindex:"
    get_lbi_status
    if [ ${GET_LBI_STATUS_RTN} -eq 0 ]; then
        rm -f lbistdout
        cd $SCRIPTDIR
        jobs &>/dev/null
        eval "$PYTHON2/bin/python lbindex start 2> lbistderr 1> lbistdout &"
        LBI_EXIT_CODE_R=$?
        new_job_started="$(jobs -n)"
        if [ -n "$new_job_started" ]; then
            PID=$!
        else
            PID=
        fi

        # NOTE: Como a saída p/ "lbistderr" e "lbistdout" é assíncrona usamos
        # um sleep de 2 segundos (pode haver dessincronia)! By Questor
        sleep 2

        LBISTDOUT=$(<lbistdout)
        LBISTDERR=$(<lbistderr)
        rm -f lbistdout
        rm -f lbistderr

        if [[ $LBISTDOUT != *"Starting daemon ..."* ]] && [[ $LBISTDERR != "" ]]; then
            echo "                                           [FAILED]"
            echo "$LBISTDOUT$LBISTDERR"
            f_set_exit_code $LBI_EXIT_CODE_R
            stop_services "only_pserve"
        else
            echo "                                           [  OK  ]"
            f_set_exit_code $LBI_EXIT_CODE_R
        fi
    else
        echo ""
    fi
}

# NOTE: Printa o status do serviço LBI! By Questor
status_lbi() {
    get_lbi_status
    if [ ${GET_LBI_STATUS_RTN} -eq 0 ]; then
        echo "lbindex is stopped"
    else
        echo "lbindex is running..."
    fi
}

# NOTE: Reinicia o LBI! By Questor
restart_lbi() {
    stop_lbi
    start_lbi
}

# NOTE: Interface para passar comandos p/ LBI ou exibir o help! By Questor
CMD_NOW=""
cmd_lbi() {
    if [[ "$CMD_NOW" != *"-h"* ]] && [[ "$CMD_NOW" != *"--help"* ]]; then
        printf "Performing cmd:"
    fi
    get_lbi_status
    if [ ${GET_LBI_STATUS_RTN} -eq 1 ]; then
        f_get_stderr_stdout "cd $SCRIPTDIR && $PYTHON2/bin/python lbindex $CMD_NOW"
        if [[ $F_GET_STDERR_R != "" ]]; then
            echo "                                             [FAILED]"
            echo "$F_GET_STDOUT_R$F_GET_STDERR_R"
            f_set_exit_code $F_GET_EXIT_CODE_R
        else
            if [[ "$CMD_NOW" != *"-h"* ]] && [[ "$CMD_NOW" != *"--help"* ]]; then
                echo "                                             [  OK  ]"
            fi
            echo "$F_GET_STDOUT_R"
            f_set_exit_code $F_GET_EXIT_CODE_R
        fi
    else
        echo "                                             [FAILED]"
        f_set_exit_code 1
    fi
}

if [[ "$@" != *"cmd"* ]] && [[ "$@" != *"-h"* ]] && [[ "$@" != *"--help"* ]]; then

    # NOTE: Usamos "$@" ao invés "$1" por ser mais seguro, pois "$@" traz todos 
    # os parâmetros após o comando diferente de "$1" onde "start foo" 
    # dispararia "start" no serviço! By Questor
    case "$@" in
        start)
            start_services
        ;;
        stop)
            stop_services
        ;;
        restart)
            restart_services
        ;;
        status)
            status_services
        ;;
        help)
            help_services
        ;;
        *)
            echo "Usage: pservemg {start|stop|restart|status|help|cmd -a}"
            f_set_exit_code 1
        ;;
    esac
else
    CMD_NOW="$@"
    cmd_lbi
fi

exit $F_SET_EXIT_CODE_R
