#!/usr/bin/bash
VERSION=0.0.1

creds=
help=
ddb_host=
grpc_port="20678"
indielinks_config='/etc/indielinks.toml '
indielinks_group=indielinks
indielinks_state='/var/run/indielinks'
indielinks_user=indielinks
local_port="20677"
port="20676"
nargs=0
no_systemd=
prev_option=
region=
scylla_host=
verbose=
version=
for option
do
    # If the previous option required an argument, assign it now.
    if test -n "$prev_option"; then
        eval $prev_option=\$option
        prev_option=
        nargs=$(($nargs+1))
        continue
    fi

    # Parse out the argument option in $option, if present.
    case $option in
        *=?*) optarg=$(expr "X$option" : '[^=]*=\(.*\)') ;;
        *=)   optarg= ;;
        *)    optarg=yes ;;
    esac

    # Options are handled here:
    case $option in
        -C | --config)
	        nargs=$(($nargs+1));
            prev_option=indielinks_config;;
        -C=* | --config=*)
	        nargs=$(($nargs+1));
            indielinks_config=$optarg;;
        -c | --creds | --credentials)
	        nargs=$(($nargs+1));
            prev_option=creds;;
        -c=* | --creds=* | --credentials=*)
	        nargs=$(($nargs+1));
            creds=$optarg;;
        -d | --ddb | --ddb-host)
	        nargs=$(($nargs+1));
            prev_option=ddb_host;;
        -d=* | --ddb=* | --ddb-host=*)
	        nargs=$(($nargs+1));
            ddb_host=$optarg;;
        -G | --group | --indielinks-group)
	        nargs=$(($nargs+1));
            prev_option=indielinks_group;;
        -G=* | --group=* | --indielinks-group=*)
	        nargs=$(($nargs+1));
            indielinks_group=$optarg;;
        -g | --grpc-port | --indielinks-grpc-port)
	        nargs=$(($nargs+1));
            prev_option=grpc_port;;
        -g=* | --grpc-port=* | --indielinks-grpc-port=*)
	        nargs=$(($nargs+1));
            indielinks_grpc_port=$optarg;;
        -h | --he | --hel | --help)
	        nargs=$(($nargs+1));
            help=yes;;
        -L | --local-port | --indielinks-local-port)
	        nargs=$(($nargs+1));
            prev_option=local_port;;
        -L=* | --local_port=* | --indielinks-local-port=*)
	        nargs=$(($nargs+1));
            indielinks_local_port=$optarg;;
        -p | --port | --indielinks-port)
	        nargs=$(($nargs+1));
            prev_option=port;;
        -p=* | --port=* | --indielinks-port=*)
	        nargs=$(($nargs+1));
            indielinks_port=$optarg;;
        -r | --region)
	        nargs=$(($nargs+1));
            prev_option=region;;
        -r=* | --region=*)
	        nargs=$(($nargs+1));
            region=$optarg;;
        -S | --state | --indielinks-state)
	        nargs=$(($nargs+1));
            prev_option=indielinks_state;;
        -S=* | --state=* | --indielinks-state=*)
	        nargs=$(($nargs+1));
            indielinks_state=$optarg;;
        -s | --scylla | --scylla-host)
	        nargs=$(($nargs+1));
            prev_option=scylla_host;;
        -s=* | --scylla=* | --scylla-host=*)
	        nargs=$(($nargs+1));
            scylla_host=$optarg;;
        -N | --no-systemd)
	        nargs=$(($nargs+1));
            no_systemd="yes";;
        -u | --user | --indielinks-user)
	        nargs=$(($nargs+1));
            prev_option=indielinks_user;;
        -u=* | --user=* | --indielinks-user=*)
	        nargs=$(($nargs+1));
            indielinks_user=$optarg;;
        -v | --verb | --verbose)
	        nargs=$(($nargs+1));
            verbose=yes;;
        -V | --vers | --version)
	        nargs=$(($nargs+1));
            version=yes;;
        -*)
            cat >&2 <<EOF
Unrecognized option '$option'.
Try 'indielinks-post-install --help' for more information.
EOF
            exit 2;;
	    *)
	        # $@ now contains the arguments, $# the number of arguments
	        shift $nargs;
	        break;;
    esac

done

if test -n "${help}"; then
    cat <<EOF
indielinks-post-install -- indielinks post-installation script

Usage:

    indielinks-post-install [OPTION...]

Options:

    -h, --help      Print this message & exit
    -V, --version   Print this script's version & exit
    -v, --verbose   Produce prolix output
    -c CREDS, --creds=CREDS Provide credentials for ScyllaDB
                    in the form "user,password" (for DynamoDB,
                    this will be "keyID,secretKey")
    -d HOST, --ddb-host) The host at which the DynamoDB API
                    is being hosted (presumably, this will be
                    the ScyllaDB Alternator interface, something
                    like "localhost:9042")
    -s HOST, --scylla=HOST  Socket address at which ScyllaDB
                    can be reached (e.g. "127.0.0.1:9042")
    -p PORT, --port=PORT Specify the port on which your
                    local indielinks is hosting its public
                    API (default: 20676)
    -L PORT, --local-port=PORT Specify the port on which your
                    local indielinks is hosting its
                    local/administrative API (default: 20677)
    -g PORT, --grpc-port=PORT Specify the port on which your
                    local indielinks is hosting its
                    gRPC API (default: 20678)
    -r REGION, --region=REGION   The AWS region in which to
                    to use DynamoDB
    -N, --no-systemd  Specify this flag if you're running
                    indielinks as a standalone, SysV daemon,
                    and not under systemd (the default)
    -u=UNAME, --user=UNAME Specify the name of the user under
                    which to run indielinks (default 'indielinks')
    -G=GNAME, --group=GNAME Specify the name of the group under
                    which to run indielinks (default 'indielinks')
    -S=DIR, --state=DIR  Directory that indielinks should use
                    as its local state directory (default
                    /var/run/indielinks)

Notes

When running indielinks under systemd, you may be prompted
for your sudo password (to stop & start the systemd unit).
EOF
    exit 0
fi

if test -n "${version}"; then
    cat <<EOF
indielinks-post-install $VERSION
EOF
    exit 0
fi

if test -n "${verbose}"; then
    set -x
fi

# I should really tighten-up argument validation, here

# stop indielinks, if it's running
if test -n "${no_systemd}"; then
    
    if test -r /var/run/indielinks/indielinks.pid; then
        pid=$(cat /var/run/indielinks.pid)
        echo -n "Stopping indielinks (PID $pid)..."
        set +e # Failure here is not fatal
        indielinks-ctl stop
        rm /var/run/indielinks/indielinks.pid
        echo -n "done."
    fi  

else

    sudo systemctl stop indielinks
fi

set -e

# run the schema migrations
schema_args="-p"
echo -n "Creating/updating the indielinks schema at "
if test -n "$ddb_host"; then
    echo -n "$ddb_host..."
    schema_args="${schema_args} ddb"
    if test -n "${creds}"; then
        schema_args="${schema_args} -c ${creds}"
    fi
    schema_args="${schema_args} ${ddb_host}"
elif test -n "$region"; then
    echo -n "$region..."
    schema_args="${schema_args} ddb"
    if test -n "${creds}"; then
        schema_args="${schema_args} -c ${creds}"
    fi
    schema_args="${schema_args} ${region}"
else
    echo -n "$scylla_host..."
    schema_args="${schema_args} scylla"
    if test -n "${creds}"; then
        schema_args="${schema_args} -c ${creds}"
    fi
    schema_args="${schema_args} ${scylla_host}"
fi
rust_log=debug,aws_config=info,aws_runtime=info,aws_sdk_sts=info,aws_sigv4=info,aws_smithy_runtime=info,aws_smithy_runtime_api=info,hyper=info,openraft=info,opentelemetry_sdk=info
RUST_LOG=${rust_log} indielinks-schemas ${schema_args}
echo "done."

# 3. start indielinks
echo -n "Starting indielinks..."
if test -n "${no_systemd}"; then
    indielinks-ctl -v -u $indielinks_user -g $indielinks_group -L $indielinks_state -c $indielinks_config start
else
    sudo systemctl start indielinks
fi
echo "done."

# healthcheck the new instance
echo -n "Waiting for your indielinks server to healthcheck"
sleep=0.5
# curl can fail if the server isn't up, yet
set +e
status=$(curl -s http://localhost:${port}/healthcheck)
ntries=1
while [ "${status}" != "GOOD" ]; do
    echo -n "."
    sleep 0.5
    status=$(curl -s http://localhost:${port}/healthcheck)
    ntries=$(($ntries+1))
    # Give it five seconds
    if [ ${ntries} -gt 10 ]; then
        echo
        echo "indielinks failed to come up!" >&2
        exit 1
    fi
done
echo "done."

echo -n "Initializing the indielinks instance as a single-node Raft cluster..."
curl -s -H 'Content-Type: application/json' http://localhost:${local_port}/ops/cache/init-cluster \
     --data "{\"0\":{\"addr\":\"127.0.0.1:${grpc_port}\"}}"
echo "done."

