#!/bin/bash

PATH=/bin:/usr/bin:/sbin:/usr/sbin
action=$1
services_filter=${2:-default}
include_monit=1

RUNNING=0
STOPPED=3
FAILED=1

xivo_services="xivo-auth xivo-dxtora xivo-provd asterisk xivo-amid xivo-call-logs xivo-agentd xivo-dird xivo-dird-phoned"
xivo_services_mds="asterisk agid"

docker_services="agid ctid outcall stats_reports_exporter usage_writer usage_collector"
docker_services_enabled="rabbitmq config_mgt db confgend nginx webi proxy"
docker_services_xc="db_replic"
docker_services_mds="rabbitmq agid confgend outcall $docker_services_xc"

default_services="dahdi xivo-sysconfd xivo-confd $xivo_services $docker_services"
default_services_mds="dahdi xivo-sysconfd confgend db_replic outcall $xivo_services_mds"

all_services="consul $docker_services_enabled $default_services"
all_services_mds="rabbitmq db $default_services_mds"

dcomp_command="xivo-dcomp"
container_check="/usr/bin/container-check-xivo.sh"
monit_default="/etc/default/monit"
asterisk_default="/etc/default/asterisk"
XIVO_DEFAULT_FILE="/etc/default/xivo"
MAX_RETRY_SERVICE=30
xivo_disabled_file="/var/lib/xivo/disabled"
xivomds_enabled_file="/var/lib/xivo/mds_enabled"
xivoxc_enabled_file="/var/lib/xivo/xc_enabled"
is_systemd=0

if [ -f $xivomds_enabled_file ];then
    xivo_services="$xivo_services_mds"
    docker_services="$docker_services_mds"
    default_services="$default_services_mds"
    all_services="$all_services_mds"
fi

if [ -f $xivoxc_enabled_file ];then
  docker_services+=" $docker_services_xc"
  default_services+=" $docker_services_xc"
  all_services+=" $docker_services_xc"
fi

check_docker_services="$docker_services $docker_services_enabled"

if [ "$services_filter" = default ]; then
    services=$default_services
elif [ "$services_filter" = all ]; then
    services=$all_services
elif [ "$services_filter" = xivo ]; then
    services="$xivo_services $docker_services"
elif [ "$services_filter" = "xivo-nomonit" ]; then
    services="$xivo_services $docker_services"
    include_monit=0
else
    echo "Invalid service filter \"$services_filter\""
    usage
fi

if [ -d /run/systemd/system ]; then
    is_systemd=1
fi


reverse_list() {
    local service_list=$1
    /bin/echo $service_list | tac -s' '
}

reversed_services=$(reverse_list "$services")

usage() {
    cat <<-EOF
	usage : $0 action [services_filter]
	availables actions :
	    status     : print status of all xivo services
	    restart    : restart all xivo services
	    stop       : stop all xivo services
	    start      : start all xivo services
	    enable     : enable all xivo services
	    disable    : disable all xivo services

	availables services_filter :
	    xivo       : manage services only used on an active XiVO
	    default    : xivo + messaging and configuration
	    all        : default + web and database servers

	impacted services ($services_filter) : $services
	EOF

    exit 0
}

xivo_status() {
    local global_status=0
    xivo-check-db
    echo "Checking services..."
    for service in $services; do
        status=$(is_running "$service")
        if [ $status -eq $RUNNING ]; then
            echo -e "\trunning\t\t$service"
        elif [ $status -eq $STOPPED ]; then
            echo -e "\tstopped\t\t$service"
            if [ $global_status -eq 0 ]; then
                global_status=1
            fi
        else
            echo -e "\tfailed\t\t$service"
            global_status=2
        fi
    done
    return $global_status
}

xivo_enable() {
    echo "Enabling XiVO services..."
    rm -f $xivo_disabled_file
    grep -qs 'startup=' $XIVO_DEFAULT_FILE
    if [ $? -eq 0 ]; then
        sed -i 's/startup=no/startup=yes/' $XIVO_DEFAULT_FILE
    else
        echo startup=yes >> $XIVO_DEFAULT_FILE
    fi
    enable_asterisk

    if [ $include_monit -eq 1 ]; then
        enable_monit
    fi
}

xivo_disable() {
    echo "Disabling XiVO services..."
    touch $xivo_disabled_file
    grep -qs 'startup=' $XIVO_DEFAULT_FILE
    if [ $? -eq 0 ]; then
        sed -i 's/startup=yes/startup=no/' $XIVO_DEFAULT_FILE
    else
        echo startup=no >> $XIVO_DEFAULT_FILE
    fi
    disable_asterisk
    if [ $include_monit -eq 1 ]; then
        disable_monit
    fi
}

disable_asterisk() {
    if [ -f $asterisk_default ]; then
        sed -i 's/RUNASTERISK=yes/RUNASTERISK=no/' $asterisk_default
    fi
}

enable_asterisk() {
    if [ -f $asterisk_default ]; then
        sed -i 's/RUNASTERISK=no/RUNASTERISK=yes/' $asterisk_default
    fi
}

disable_monit() {
    sed -i 's/startup=1/startup=0/' $monit_default  # older monit
    sed -i 's/START=yes/START=no/' $monit_default
    # systemctl disable also updates sysv links via update-rc.d
    systemctl disable monit &> /dev/null
}

stop_monit() {
    if [ $include_monit -eq 1 ]; then
        service monit stop > /dev/null
    fi
}

enable_monit() {
    sed -i 's/startup=0/startup=1/' $monit_default  # older monit
    sed -i 's/START=no/START=yes/' $monit_default
    systemctl enable monit &> /dev/null
}

start_monit() {
    if [ $include_monit -eq 1 ]; then
        service monit start > /dev/null
    fi
}

close_sip_port() {
    echo "Closing port 5060."
    iptables -n --list | grep -q '^DROP.*5060'
    if [ $? -eq 1 ]; then
        iptables -I INPUT 1 -p udp --dport 5060 -j DROP
    fi
}

open_sip_port() {
    echo "Opening port 5060."
    iptables -n --list | grep -q '^DROP.*5060'
    if [ $? -eq 0 ]; then
        iptables -D INPUT -p udp --dport 5060 -j DROP
    fi
}

wait_for_service() {
    sleep 1
    echo -n "."
    _x=$(( $_x + 1 ))
    if [ $_x -eq $MAX_RETRY_SERVICE ]; then
        echo " NOK"
        echo "ERR: Stop after $_x retry."
        open_sip_port
        exit 1
    fi
}

is_xivo_enabled() {
    if [ $is_systemd -eq 0 ]; then
        grep -q 'startup=yes' $XIVO_DEFAULT_FILE
    else
        test ! -f $xivo_disabled_file
    fi
    echo $?
}

is_enabled() {
    local service=$1
    enabled=0
    if [ $service = "asterisk" ]; then
        if [ $is_systemd -eq 0 ]; then
            grep -q 'RUNASTERISK=yes' $asterisk_default
            enabled=$?
        else
            test ! -f $xivo_disabled_file
            enabled=$?
        fi
    fi
    for srv in $xivo_services; do
        if [ $srv != "asterisk" ]; then
            if [ $srv = $service ]; then
                enabled=$(is_xivo_enabled)
            fi
        fi
    done
    echo $enabled
}

is_docker_service() {
    local re="\<$1\>"
    if [[ $check_docker_services =~ $re ]]; then
        return 0
    else
        return 1
    fi
}

is_enabled_docker_service() {
    local re="\<$1\>"
    if [[ $docker_services_enabled =~ $re ]]; then
        return 0
    else
        return 1
    fi
}

is_postgres_11_running() {
    result=$(psql -U postgres --quiet -tAc "SELECT 1 FROM pg_catalog.pg_database WHERE datname='$1'" 2> /dev/null)

    [ $? -eq 0 ] && [ "$result" = "1" ]
}

is_running() {
    local service=$1
    local running=$RUNNING
    if [ "$service" = "db" ] ; then
        $container_check $service
        running=$?
        if [ $running -eq $RUNNING ]; then
            if ! is_postgres_11_running asterisk; then
                running=$FAILED
            fi
        fi
    elif is_docker_service "$service" ; then
        $container_check $service
        running=$?
    else
        service $service status > /dev/null
        running=$?
    fi
    echo $running
}

start_docker_service() {
    local service=$1
    if [ $(is_xivo_enabled) -eq 0 ] || is_enabled_docker_service "$service"; then
        $dcomp_command up -d $service > /dev/null
        while [ $(is_running "$service") -ne $RUNNING ]; do
            wait_for_service
        done
    fi
}

start_services() {
    local services=$1
    for service in $services; do
        enabled=$(is_enabled $service)
        running=$(is_running $service)
        if [ $enabled -eq 0 ] && [ $running -ne $RUNNING ]; then
            if is_docker_service "$service" ; then
                start_docker_service $service
            elif [ $is_systemd -eq 0 ]; then
                if [ -f /etc/init.d/$service ]; then
                    invoke-rc.d $service start > /dev/null
                    echo -en "\tstarting $service ..."
                    _x=0
                    while [ $(is_running "$service") -ne $RUNNING ]; do
                        wait_for_service
                    done
                    echo " OK"
                fi
            else
                echo -en "\tstarting $service ..."
                if ! systemctl start $service; then
                    echo " NOK"
                    open_sip_port
                    exit 1
                fi
                echo " OK"
            fi
        elif [ $enabled -ne 0 ]; then
            echo -e "\t$service is disabled"
        fi
    done

    if [ $(is_xivo_enabled) -ne 0 ]; then
        for service in $docker_services; do
            echo -e "\t$service is disabled"
        done
    fi

    start_monit
}

stop_services() {
    stop_monit
    local services=$1
    for service in $services; do
        if [ $is_systemd -eq 0 ]; then
            running=$(is_running "$service")
            if [ $running -eq $RUNNING ]; then
                if is_docker_service "$service" ; then
                    $dcomp_command stop $service > /dev/null
                elif [  -f /etc/init.d/$service ]; then
                    invoke-rc.d $service stop > /dev/null
                fi
            fi
        else
            if is_docker_service "$service" ; then
                $dcomp_command stop $service > /dev/null
            else
                systemctl stop $service
            fi
        fi
    done
}

xivo_start_and_open() {
    local service_list=$1
    echo "Waiting for services to start successfully..."
    start_services "$service_list"
    open_sip_port
}

xivo_close_and_stop() {
    local service_list=$1
    close_sip_port
    echo "Waiting for services to stop successfully..."
    stop_services "$service_list"
}

xivo_start() {
    xivo_start_and_open "$services"
    echo "XiVO fully booted"
}

xivo_stop() {
    xivo_close_and_stop "$reversed_services"
}

xivo_restart() {
    xivo_stop
    xivo_start
}

case $action in
    status|monitor)  xivo_status;;
    force-reload|restart) xivo_restart;;
    start)   xivo_start;;
    stop)    xivo_stop;;
    enable)  xivo_enable;;
    disable) xivo_disable;;
    *) usage;;
esac
