#!/bin/bash

# Colors
RESTORE='\033[0m'
RED='\033[00;31m'
GREEN='\033[00;32m'
YELLOW='\033[00;33m'
BLUE='\033[00;34m'
PURPLE='\033[00;35m'
CYAN='\033[00;36m'
LIGHTGREY='\033[00;37m'
# end colors

PID_LOCATION="/var/run/"

LOG_LOCATION="/var/log/scripts/"

ACADEMICS_TASK_QUEUE="academics-task-queue-worker"
ACADEMICS_EMAIL_QUEUE="academics-intimation-queue-worker"
ACADEMICS_SMS_QUEUE="academics-sms-queue-worker"
EXTERNAL_API_QUEUE="external-api-queue-worker"
ACADEMICS_SCHEDULER_RUNNER_QUEUE="academics-scheduler-runner-queue-worker"
OBE_CO_PO_CALCULATION_QUEUE="obe-co-po-calculation-queue-worker"

SER_ACADEMICS_TASK_Q="academics-task-queue"
SER_ACADEMICS_INTIMATION_Q="academics-intimation-queue"
SER_ACADEMICS_SMS_Q="academics-sms-queue"
SER_EXTERNAL_API_Q="external-api-queue"
SER_ACADEMICS_SCHEDULER_RUNNER_Q="academics-scheduler-runner-queue"
SER_OBE_CO_PO_CALCULATION_Q="obe-co-po-calculation-queue"

BASEDIR=$(dirname $(realpath "$0"))
cd $BASEDIR

start_worker(){
    SCRIPT=$1
    LOG_FILE=$2
    PID_FILE=$3
    QUEUE_NAME=$4
    if [ -f "$PID_FILE" ] &&  kill -0 `cat $PID_FILE` > /dev/null 2>&1
    then
        printf "$RED $SCRIPT already running $RESTORE\n"
    else
        nohup php $SCRIPT $QUEUE_NAME $NUCLEUS_CONF >> $LOG_FILE 2>&1 &
        echo $! > $PID_FILE
        printf "\nStarted $SCRIPT $QUEUE_NAME\n"
    fi
}

stop_worker(){
    SCRIPT=$1
    PID_FILE=$2
    QUEUE_NAME=$3
    if [ -f "$PID_FILE" ]
    then
        kill `cat $PID_FILE`
        rm $PID_FILE
        printf "\nStopped $SCRIPT $QUEUE_NAME\n"
    fi
}

stop_worker_gracefully(){
    SCRIPT=$1
    PID_FILE=$2
    QUEUE_NAME=$3
    if [ -f "$PID_FILE" ]
    then
        current_pid=$(cat $PID_FILE)
        # If process exist, send SIGTERM to the process
        if kill -0 `cat $PID_FILE` > /dev/null 2>&1; then
            kill -SIGTERM `cat $PID_FILE`
        fi
        # Wait if the process is still running and the PID in the file is same as the one when the script has called
        current_time=$(date +"%Y-%m-%d %H:%M:%S")
        echo "$SCRIPT: Waiting to stop $current_time"
        while kill -0 `cat $PID_FILE` > /dev/null 2>&1 && [ "$current_pid" = "`cat $PID_FILE`" ]; do
            sleep 1
        done
        current_time=$(date +"%Y-%m-%d %H:%M:%S")
        echo "$SCRIPT: Waiting End $current_time"
        # If the PID when the script has called has changed to some other in the file, it means some other script has already terminated the process with this PID and started another. So no need to remove this file
        if [ "$current_pid" != "`cat $PID_FILE`" ]
        then
            printf "\nAlready terminated $SCRIPT $QUEUE_NAME\n"
        else
            rm $PID_FILE
            printf "\nStopped $SCRIPT $QUEUE_NAME\n"
        fi
    fi
}

execute_action(){
    ACTION=$1
    SCRIPT=$2
    LOG_FILE=$3
    PID_FILE=$4
    QUEUE_NAME=$5
    case $ACTION
    in
        "start")
            start_worker $SCRIPT $LOG_FILE $PID_FILE $QUEUE_NAME
            ;;
        "stop")
            stop_worker $SCRIPT $PID_FILE $QUEUE_NAME
            ;;
        "stop_gracefully")
            stop_worker_gracefully $SCRIPT $PID_FILE $QUEUE_NAME
            ;;
        "restart")
            execute_action stop $SCRIPT $LOG_FILE $PID_FILE $QUEUE_NAME
            execute_action start $SCRIPT $LOG_FILE $PID_FILE $QUEUE_NAME
            ;;
        "gracefull_restart")
            execute_action stop_gracefully $SCRIPT $LOG_FILE $PID_FILE $QUEUE_NAME
            execute_action start $SCRIPT $LOG_FILE $PID_FILE $QUEUE_NAME
            ;;
        *)
            echo "Invalid operation"
            ;;
    esac
}

academics_task_queue_worker(){
    ACTION=$1
    PID_FILE="$PID_LOCATION$ACADEMICS_TASK_QUEUE.pid"
    LOG_FILE="$LOG_LOCATION$ACADEMICS_TASK_QUEUE.log"
    QUEUE_NAME="ACADEMICS_TASK_QUEUE"
    execute_action $ACTION "academics_task_queue_worker.php" $LOG_FILE $PID_FILE $QUEUE_NAME
}


academics_intimation_queue(){
    ACTION=$1
    PID_FILE="$PID_LOCATION$ACADEMICS_EMAIL_QUEUE.pid"
    LOG_FILE="$LOG_LOCATION$ACADEMICS_EMAIL_QUEUE.log"
    QUEUE_NAME="ACADEMICS_EMAIL_QUEUE"
    execute_action $ACTION "academics_intimation_queue.php" $LOG_FILE $PID_FILE $QUEUE_NAME
}

academics_sms_queue(){
    ACTION=$1
    PID_FILE="$PID_LOCATION$ACADEMICS_SMS_QUEUE.pid"
    LOG_FILE="$LOG_LOCATION$ACADEMICS_SMS_QUEUE.log"
    QUEUE_NAME="ACADEMICS_SMS_QUEUE"
    execute_action $ACTION "academics_sms_queue.php" $LOG_FILE $PID_FILE $QUEUE_NAME
}

external_api_queue(){
    ACTION=$1
    PID_FILE="$PID_LOCATION$EXTERNAL_API_QUEUE.pid"
    LOG_FILE="$LOG_LOCATION$EXTERNAL_API_QUEUE.log"
    QUEUE_NAME="EXTERNAL_API_QUEUE"
    execute_action $ACTION "external_api_queue_worker.php" $LOG_FILE $PID_FILE $QUEUE_NAME
}

academics_scheduler_runner_queue(){
    ACTION=$1
    PID_FILE="$PID_LOCATION$ACADEMICS_SCHEDULER_RUNNER_QUEUE.pid"
    LOG_FILE="$LOG_LOCATION$ACADEMICS_SCHEDULER_RUNNER_QUEUE.log"
    QUEUE_NAME="ACADEMICS_SCHEDULER_RUNNER_QUEUE"
    execute_action $ACTION "academics_scheduler_runner_queue_worker.php" $LOG_FILE $PID_FILE $QUEUE_NAME
}

obe_co_po_calculation_queue(){
    ACTION=$1
    PID_FILE="$PID_LOCATION$OBE_CO_PO_CALCULATION_QUEUE.pid"
    LOG_FILE="$LOG_LOCATION$OBE_CO_PO_CALCULATION_QUEUE.log"
    QUEUE_NAME="OBE_CO_PO_CALCULATION_QUEUE"
    execute_action $ACTION "obe_co_po_calculation_queue_worker.php" $LOG_FILE $PID_FILE $QUEUE_NAME
}

###   MAIN   ###

if [ "$(whoami)" != "root" ]
then
    printf "$RED Need to run this script using$YELLOW sudo $RESTORE \n"
    exit 1
fi

# Read nucleus conf from .cli.env
NUCLEUS_CONF=$(grep NUCLEUS_CONF ../.cli.env | xargs)
if [ -z "$NUCLEUS_CONF" ]
then
    printf "$RED Could not find NUCLEUS_CONF in .cli.env, \nPlease add variable NUCLEUS_CONF in ../cli.env\n$RESTORE"
    exit 1
fi

# create the log file location if it does not exists
mkdir -p $LOG_LOCATION

OP=$1
SERVICE=$2

case $OP in
    "start")
        case $SERVICE in
            $SER_ACADEMICS_TASK_Q)
                academics_task_queue_worker start
                ;;
            $SER_ACADEMICS_INTIMATION_Q)
                academics_intimation_queue start
                ;;
            $SER_ACADEMICS_SMS_Q)
                academics_sms_queue start
                ;;
            $SER_EXTERNAL_API_Q)
                external_api_queue start
                ;;
            $SER_ACADEMICS_SCHEDULER_RUNNER_Q)
                academics_scheduler_runner_queue start
                ;;
            $SER_OBE_CO_PO_CALCULATION_Q)
                obe_co_po_calculation_queue start
                ;;
            *)
                 if [ -z $SERVICE ]
                    then
                        academics_task_queue_worker start
                        academics_intimation_queue start
                        academics_sms_queue start
                        external_api_queue start
                        academics_scheduler_runner_queue start
                        obe_co_po_calculation_queue start
                 else
                    printf "$RED Invalid service. Possible values are : [$SER_ACADEMICS_TASK_Q,$SER_ACADEMICS_INTIMATION_Q,$SER_ACADEMICS_SMS_Q,$SER_EXTERNAL_API_Q,$SER_ACADEMICS_SCHEDULER_RUNNER_Q,$SER_OBE_CO_PO_CALCULATION_Q]\n"
                 fi
                 ;;
        esac
        ;;
    "stop")
        case $SERVICE in
            $SER_ACADEMICS_TASK_Q)
                academics_task_queue_worker stop
                ;;
            $SER_ACADEMICS_INTIMATION_Q)
                academics_intimation_queue stop
                ;;
            $SER_ACADEMICS_SMS_Q)
                academics_sms_queue stop
                ;;
            $SER_EXTERNAL_API_Q)
                external_api_queue stop
                ;;
            $SER_ACADEMICS_SCHEDULER_RUNNER_Q)
                academics_scheduler_runner_queue stop
                ;;
            $SER_OBE_CO_PO_CALCULATION_Q)
                obe_co_po_calculation_queue stop
                ;;
            *)
                 if [ -z $SERVICE ]
                    then
                        academics_task_queue_worker stop
                        academics_intimation_queue stop
                        academics_sms_queue stop
                        external_api_queue stop
                        academics_scheduler_runner_queue stop
                        obe_co_po_calculation_queue stop
                 else
                    printf "$RED Invalid service. Possible values are : [$SER_ACADEMICS_TASK_Q,$SER_ACADEMICS_INTIMATION_Q,$SER_ACADEMICS_SMS_Q,$SER_EXTERNAL_API_Q,$SER_ACADEMICS_SCHEDULER_RUNNER_Q,$SER_OBE_CO_PO_CALCULATION_Q]\n"
                 fi
                 ;;
        esac
        ;;
    "restart")
        case $SERVICE in
            $SER_ACADEMICS_TASK_Q)
                academics_task_queue_worker restart
                ;;
            $SER_ACADEMICS_INTIMATION_Q)
                academics_intimation_queue restart
                ;;
            $SER_ACADEMICS_SMS_Q)
                academics_sms_queue restart
                ;;
            $SER_EXTERNAL_API_Q)
                external_api_queue restart
                ;;
            $SER_ACADEMICS_SCHEDULER_RUNNER_Q)
                academics_scheduler_runner_queue restart
                ;;
            $SER_OBE_CO_PO_CALCULATION_Q)
                obe_co_po_calculation_queue restart
                ;;
            *)
                 if [ -z $SERVICE ]
                    then
                        academics_task_queue_worker restart
                        academics_intimation_queue restart
                        academics_sms_queue restart
                        external_api_queue restart
                        academics_scheduler_runner_queue restart
                        obe_co_po_calculation_queue restart
                 else
                    printf "$RED Invalid service. Possible values are : [$SER_ACADEMICS_TASK_Q,$SER_ACADEMICS_INTIMATION_Q,$SER_ACADEMICS_SMS_Q,$SER_EXTERNAL_API_Q,$SER_ACADEMICS_SCHEDULER_RUNNER_Q,$SER_OBE_CO_PO_CALCULATION_Q]\n"
                 fi
                 ;;
        esac
        ;;
    "gracefull_restart")
        case $SERVICE in
            $SER_ACADEMICS_TASK_Q)
                academics_task_queue_worker gracefull_restart
                ;;
            $SER_ACADEMICS_INTIMATION_Q)
                academics_intimation_queue gracefull_restart
                ;;
            $SER_ACADEMICS_SMS_Q)
                academics_sms_queue gracefull_restart
                ;;
            $SER_EXTERNAL_API_Q)
                external_api_queue gracefull_restart
                ;;
            $SER_ACADEMICS_SCHEDULER_RUNNER_Q)
                academics_scheduler_runner_queue gracefull_restart
                ;;
            $SER_OBE_CO_PO_CALCULATION_Q)
                obe_co_po_calculation_queue gracefull_restart
                ;;
            *)
                 if [ -z $SERVICE ]
                    then
                        academics_task_queue_worker gracefull_restart
                        academics_intimation_queue gracefull_restart
                        academics_sms_queue gracefull_restart
                        external_api_queue gracefull_restart
                        academics_scheduler_runner_queue gracefull_restart
                        obe_co_po_calculation_queue gracefull_restart
                 else
                    printf "$RED Invalid service. Possible values are : [$SER_ACADEMICS_TASK_Q,$SER_ACADEMICS_INTIMATION_Q,$SER_ACADEMICS_SMS_Q,$SER_EXTERNAL_API_Q,$SER_ACADEMICS_SCHEDULER_RUNNER_Q,$SER_OBE_CO_PO_CALCULATION_Q]\n"
                 fi
                 ;;
        esac
        ;;
    "stop_gracefully")
        case $SERVICE in
            $SER_ACADEMICS_TASK_Q)
                academics_task_queue_worker stop_gracefully
                ;;
            $SER_ACADEMICS_INTIMATION_Q)
                academics_intimation_queue stop_gracefully
                ;;
            $SER_ACADEMICS_SMS_Q)
                academics_sms_queue stop_gracefully
                ;;
            $SER_EXTERNAL_API_Q)
                external_api_queue stop_gracefully
                ;;
            $SER_ACADEMICS_SCHEDULER_RUNNER_Q)
                academics_scheduler_runner_queue stop_gracefully
                ;;
            $SER_OBE_CO_PO_CALCULATION_Q)
                obe_co_po_calculation_queue stop_gracefully
                ;;
            *)
                 if [ -z $SERVICE ]
                    then
                        academics_task_queue_worker stop_gracefully
                        academics_intimation_queue stop_gracefully
                        academics_sms_queue stop_gracefully
                        external_api_queue stop_gracefully
                        academics_scheduler_runner_queue stop_gracefully
                        obe_co_po_calculation_queue stop_gracefully
                 else
                    printf "$RED Invalid service. Possible values are : [$SER_ACADEMICS_TASK_Q,$SER_ACADEMICS_INTIMATION_Q,$SER_ACADEMICS_SMS_Q,$SER_EXTERNAL_API_Q,$SER_ACADEMICS_SCHEDULER_RUNNER_Q,$SER_OBE_CO_PO_CALCULATION_Q]\n"
                 fi
                 ;;
        esac
        ;;
    *)
        printf "$RED Invalid operation. Available operations:$RESTORE \n\n"
        printf "$YELLOW sudo ./manage_worker.sh start [SERVICE]$BLUE To start all queue workers\n"
        printf "$YELLOW sudo ./manage_worker.sh stop [SERVICE]$BLUE To stop all queue workers\n"
        printf "$YELLOW sudo ./manage_worker.sh restart [SERVICE]$BLUE To restart all queue workers\n\n\n"
        printf "$YELLOW sudo ./manage_worker.sh gracefull_restart [SERVICE]$BLUE To restart all queue workers gracefully after validating message consumption\n"
        printf "$YELLOW sudo ./manage_worker.sh stop_gracefully [SERVICE]$BLUE To stop all queue workers gracefully\n\n\n"
        printf "$CYAN SERVICE $PURPLE (optional) could be any one of [$SER_ACADEMICS_TASK_Q, $SER_ACADEMICS_INTIMATION_Q,$SER_ACADEMICS_SMS_Q,$SER_EXTERNAL_API_Q,$SER_ACADEMICS_SCHEDULER_RUNNER_Q,$SER_OBE_CO_PO_CALCULATION_Q]; If nothing is specified all services will be considered\n\n$RESTORE"
        ;;
esac
