#!/bin/sh
#########################################################################
# (c) 2022 Copyright, Real-Time Innovations. All rights reserved.       #
# No duplications, whole or partial, manual or electronic, may be made  #
# without express written permission.  Any such copies, or              #
# revisions thereof, must display this notice unaltered.                #
# This code contains trade secrets of Real-Time Innovations, Inc.       #
#########################################################################

####################################################################
#
# Function to display usage
#
####################################################################
usage() { # Function: Display the usage
    echo "\nUsage: $scriptname [options]\n"
    echo ""
    echo ""
    echo "  -c <json_file>      - Create all the required configuration from a JSON file."
    echo "                         More information about how to create this JSON file in the"
    echo "                         Connext Observability Framework documentation."
    echo "  -i                  - Initialize and run the Connext Observability Framework"
    echo "  -s                  - Start an existing Connext Observability Framework"
    echo "  -t                  - Terminate the running Connext Observability Framework"
    echo "  -d                  - Delete all components of the existing Connext Observability Framework"
    echo ""
    echo " These options are mutually exclusive and are used to control the"
    echo " Connext Observability Framework run time environment."
    echo ""
    echo "HELP Option:"
    echo ""
    echo " -h                  - Help"
    echo ""
    echo " The HELP option prints this usage."
    echo ""
    echo "\n"
}

####################################################################
#
# Function to create required local variables and call rticommon script
#
####################################################################
setupEnvironment() {
    script_version=7.7.0.0

    rticommon_script_dir=$script_dir/../resource/scripts
    rticommon_script_name=rticommon.sh

    if [ ! -f "$rticommon_script_dir/$rticommon_script_name" ]
    then
        rticommon_script_dir=$script_dir/../../ndds.4.1/resource/scripts
    fi

    . "$rticommon_script_dir/$rticommon_script_name"

    home_observability_dir=$home_user_config_dir/observability
    resource_observability_dir=$app_support_dir/observability
}

####################################################################
#
# Function to setup the Observability Framework
#
####################################################################
setupObservabilityFramework() {

    # setup the local environment
    setupEnvironment

    # check to see if Observability Framework already exists
    if [ -d "$home_observability_dir" ]

    then
        # directory exists so print error
        echo ""
        echo "  ********************************************************************************"
        echo "  *"
        echo "  *  The Connext Observability Framework already exist in:"
        echo "  *      $home_observability_dir"
        echo "  *"
        echo "  *  Remove or rename the directory manually if you want to start over ..."
        echo "  *"
        echo "  ********************************************************************************"
        echo ""
    else
        # directory does NOT exist so install the Observability Framework

        # get confirmation of license acceptance
        echo ""
        echo "  *****************************************************************************"
        echo "  * DISCLAIMER"
        echo "  *"
        echo "  * The Observability Docker configuration scripts provided herein instruct"
        echo "  * your system to download and run container images from third-party"
        echo "  * repositories. These include:"
        echo "  *"
        echo "  * Prometheus"
        echo "  *   (https://hub.docker.com/r/prom/prometheus),"
        echo "  * Grafana Loki"
        echo "  *   (https://hub.docker.com/r/grafana/loki),"
        echo "  * Grafana"
        echo "  *   (https://hub.docker.com/r/grafana/grafana-enterprise),"
        echo "  * NGINX"
        echo "  *   (https://hub.docker.com/_/nginx),"
        echo "  * and OpenTelemetry Collector"
        echo "  *   (https://hub.docker.com/r/otel/opentelemetry-collector-contrib)."
        echo "  *"
        echo "  * Separate Software: These third-party software differ and are separate from"
        echo "  * RTI software. They execute as standalone processes that communicate with"
        echo "  * RTI products solely via standard network interfaces. They are not linked"
        echo "  * to, nor do they form a derivative work with, RTI’s proprietary software."
        echo "  *"
        echo "  * License Compliance: These third-party images are subject to their own"
        echo "  * respective license terms, which may differ from your RTI license agreement."
        echo "  * RTI DOES NOT DISTRIBUTE THESE THIRD-PARTY IMAGES AND PROVIDES THESE"
        echo "  * SCRIPTS \"AS IS\" FOR CONVENIENCE ONLY. IT IS YOUR RESPONSIBILITY TO ENSURE"
        echo "  * THAT YOUR USE OF THESE THIRD-PARTY COMPONENTS COMPLIES WITH THEIR APPLICABLE"
        echo "  * LICENSES (INCLUDING ANY OPEN SOURCE OR COMMERCIAL SUBSCRIPTION REQUIREMENTS"
        echo "  * FOR ENTERPRISE VERSIONS)."
        echo "  *****************************************************************************"
        echo ""

        # get user confirmation
        while true; do
            read -p "Do you wish to continue setting up the Connext Observability Framework[Y/n]? " yn
            case $yn in
                [Yy]* | "" ) # accept "enter" (empty string) as default acceptance
                    break
                    ;;
                [Nn]* )
                    echo "\nConnext Observability Framework setup canceled.\n"
                    exit 0
                    ;;
                * )
                    echo "Please answer yes (y) or no (n)."
                    ;;
            esac
        done

        # Check python
        if ! [ -x "$(command -v python3)" ]; then
            if ! [ -x "$(command -v python)" ]; then
                echo ""
                echo "  ********************************************************************************"
                echo "  *"
                echo "  * Required Python installation was not found !"
                echo "  *"
                echo "  *   We tried looking for python and python3 in your environment."
                echo "  *   Please make sure a python installation is available."
                echo "  *"
                echo "  ********************************************************************************"
                echo ""

                exit 1
            else
                pythonCommand="python"
            fi
        else
            pythonCommand="python3"
        fi

        # Run exporter
        echo "\nGenerating configuration for the Connext Observability Framework\n"
        $pythonCommand $resource_observability_dir/main.py -i $json_file -o $home_observability_dir
    fi
}

####################################################################
#
# Function to run the Observability Framework
#
####################################################################
runObservabilityFramework() {

    # setup the local environment
    setupEnvironment

    # verify license file is available
    if [ ! -f "$RTI_LICENSE_FILE" ]
    then
        echo ""
        echo "  ********************************************************************************"
        echo "  *"
        echo "  * No license file found !"
        echo "  *"
        echo "  *   You must install your RTI license."
        echo "  *"
        echo "  ********************************************************************************"
        echo ""

        exit 1
    fi

    # test for Docker compose
    dockerComposeCommand=
    dockerVersion=`docker --version 2> /dev/null`
    dockerComposePluginVersion=`docker compose version 2> /dev/null`
    dockerComposeStandaloneVersion=`docker-compose version 2> /dev/null`
    if echo $dockerComposeStandaloneVersion | grep -Eq '^docker-compose version.'
    then
        echo ""
        echo "  ... using Standalone $dockerComposeStandaloneVersion."
        dockerComposeCommand='docker-compose'
    elif echo $dockerVersion | grep -Eq '^Docker version.'
    then
        echo ""
        echo "  ... using $dockerVersion."
        if  echo $dockerComposePluginVersion | grep -Eq '^Docker Compose version.'
        then
            echo "  ... using $dockerComposePluginVersion."
            dockerComposeCommand='docker compose'
        else
            echo ""
            echo "  ********************************************************************************"
            echo "  *"
            echo "  * The required Docker Compose plugin was not found !"
            echo "  *"
            echo "  *   You must install the Docker Compose plugin to run the"
            echo "  *   Connext Observability Framework."
            echo "  *"
            echo "  ********************************************************************************"
            echo ""

            exit 1
        fi
    else
        echo ""
        echo "  ********************************************************************************"
        echo "  *"
        echo "  * Required Docker components were not found !"
        echo "  *"
        echo "  *   You must install Docker and the Docker Compose plugin to run the"
        echo "  *   Connext Observability Framework."
        echo "  *"
        echo "  ********************************************************************************"
        echo ""

        exit 1
    fi

    # switch to Observability install dir
    cd "$home_observability_dir"

    # execute the selected function
    if [ -n "$initialize" ]
    then
        # implement -i
        echo "\nInitializing and running the Connext Observability Framework\n"
        $dockerComposeCommand up -d
    elif [ -n "$start" ]
    then
        # implement -s
        echo "\nStarting the existing Connext Observability Framework\n"
        $dockerComposeCommand start
    elif [ -n "$terminate" ]
    then
        # implement -t
        echo "\nTerminating the running Connext Observability Framework\n"
        $dockerComposeCommand stop
    elif [ -n "$cleanup" ]
    then
        # implement -c
        # get confirmation to cleanup
        echo ""
        echo "  ********************************************************************************"
        echo "  *"
        echo "  * You have requested to clean up and remove the existing Connext Observability"
        echo "  * Framework.  If you continue you will lose all changes to your current"
        echo "  * environment including:"
        echo "  *    - metric data in Prometheus"
        echo "  *    - log data in Loki"
        echo "  *    - all Grafana user and dashboard configuration"
        echo "  *"
        echo "  ********************************************************************************"
        echo ""

        # get user confirmation
        while true; do
            read -p "Do you wish to continue cleaning and removing the existing Connext Observability Framework[y/N]? " yn
            case $yn in
                [Yy]*)
                    break
                    ;;
                [Nn]* | "")  # accept "enter" (empty string) as default refusal
                    echo "\nCleaning up and removing the existing Connext Observability Framework canceled.\n"
                    exit 0
                    ;;
                * )
                    echo "Please answer yes (y) or no (n)."
                    ;;
            esac
        done

        echo "\nCleaning up and removing the existing Connext Observability Framework\n"
        $dockerComposeCommand down
        docker volume remove observability_loki_data
        docker volume remove observability_grafana_data
        docker volume remove observability_prometheus_data
        docker image rm rticom/collector-service:$host_version
    fi
}

####################################################################
#
# Script entry Point
#
####################################################################

####################################################################
# create some local variables
####################################################################
filename=$0
scriptname=`basename "$filename"`
script_dir=`cd "\`dirname "$filename"\`"; pwd`
options=0
config=0
initialize=
start=
terminate=
cleanup=
json_file=

####################################################################
# process options flags and arguments
####################################################################
while getopts ':c:istdh' flag; do

    # check to see if selected options have a valid parameter
    case "$flag" in
        c)
            if ( echo $OPTARG | grep -Eq '^-.' )
            then
                echo "\nInvalid argument \"$OPTARG\" provided for option \"-$flag\"!"
                usage
                exit 1
            fi
            ;;
    esac

    # process the options
    case "$flag" in
        c)
            json_file="$OPTARG"
            config=1
            options=$((options+1))
            ;;
        i)
            initialize=1
            options=$((options+1))
            ;;
        s)
            start=1
            options=$((options+1))
            ;;
        t)
            terminate=1
            options=$((options+1))
            ;;
        d)
            cleanup=1
            options=$((options+1))
            ;;
        h)
            usage
            exit 0
            ;;
        \?)
            echo "\nInvalid option: $OPTARG.\n"
            usage
            exit 1
            ;;
        :)
            echo "\nInvalid option: $OPTARG requires an argument.\n"
            usage
            exit 1
            ;;
    esac
done

####################################################################
# Test the options and execute the appropriate function.
####################################################################
shift $((OPTIND-1))
if [ "$#" -gt 0 ] # were there any non-option arguments
then
    echo "\nInvalid non-option argument(s).\n"
    usage
    exit 1
elif [ "$options" -eq 0 ]
then
    echo "\nRequired option not provided.\n"
    usage
    exit 1
elif [ "$options" -gt 1 ] # were there more than 1 run options
then
    echo "\nError: -i, -s, -t, -d, -c options are mutually exclusive and may only be used once!\n"
    usage
    exit 1
elif [ "$options" -eq 1 ]
then
    if [ "$config" -eq 1 ] # were there no run options
    then
        setupObservabilityFramework
    else
        runObservabilityFramework
    fi
fi

exit 0
