#!/usr/bin/env bash

BACKUP_USER="bcp"
MONGO_PASS="test1234"
BCP_NAME=""
COMPOSE_PATH="${test_dir}/docker/docker-compose.yaml"
COMPOSE_RS_PATH="${test_dir}/docker/docker-compose-rs.yaml"
COMPOSE_SINGLE_PATH="${test_dir}/docker/docker-compose-single.yaml"
PBM_TEST_CLEANUP=${PBM_TEST_CLEANUP:-true}

run() {
    local compose=$1
    local mongo_version=$2

    desc 'Start cluster'
    case $compose in
        $COMPOSE_PATH)
            start_cluster "$mongo_version"
        ;;
        $COMPOSE_RS_PATH)
            start_replset "$mongo_version" "$COMPOSE_RS_PATH"
        ;;
        $COMPOSE_SINGLE_PATH)
            start_replset "$mongo_version" "$COMPOSE_SINGLE_PATH"
        ;;
    esac

    desc 'Run tests'
    docker-compose -f $compose up tests
    EXIT_CODE=$(docker-compose -f $compose ps -q tests | xargs docker inspect -f '{{ .State.ExitCode }}')

    if [ $PBM_TEST_CLEANUP == true ]; then
        if [ $EXIT_CODE != 0 ]; then
            docker-compose -f $compose logs --no-color --tail=100
            desc 'PBM logs'
            docker-compose -f $compose exec -T agent-rs101 pbm logs -t 0 -s D -x || true
            desc 'PBM status'
            docker-compose -f $compose exec -T agent-rs101 pbm status || true
        fi

        desc 'Destroy cluster'
        destroy_cluster $compose
    fi

    exit $EXIT_CODE
}

pbm_run() {
    local cmd="$@"

    docker-compose -f $COMPOSE_PATH exec -T agent-rs101 pbm $cmd
}

mongo_run() {
    local cmd=$1
    local rs=$2

    docker-compose -f $COMPOSE_PATH exec -T "${rs}01" mongo "mongodb://${BACKUP_USER}:${MONGO_PASS}@localhost/?replicaSet=${rs}" --quiet --eval="${cmd}"
}

wait_backup() {
    set +o xtrace

    BCP_NAME=$(mongo_run "db.getSiblingDB(\"admin\").pbmBackups.find({}, {name: 1, _id: 0}).sort({start_ts: -1}).limit(1)" "cfg" | tail -n 1 | awk -F\" '{print$4}')

    retry=0
    until [ "$(mongo_run "db.getSiblingDB(\"admin\").pbmBackups.findOne({name: \"${BCP_NAME}\"}).status" cfg | tail -n 1 | tr -d '\r' )" == "done" ]; do
        sleep 1
        echo -n .
        let retry+=1
        if [ $retry -ge 120 ]; then
            mongo_run "db.getSiblingDB(\"admin\").pbmBackups.findOne({name: \"${BCP_NAME}\"})" "cfg"
            exit 1
        fi
    done
    set -o xtrace
}

wait_restore() {
    set +o xtrace

    retry=0
    until [ "$(mongo_run "db.getSiblingDB(\"admin\").pbmRestores.findOne({backup: \"${BCP_NAME}\"}).status" cfg | tail -n 1 | tr -d '\r' )" == "done" ]; do
        sleep 1
        echo -n .
        let retry+=1
        if [ $retry -ge 120 ]; then
            mongo_run "db.getSiblingDB(\"admin\").pbmRestores.findOne({backup: \"${BCP_NAME}\"})" "cfg"
            exit 1
        fi
    done
    set -o xtrace
}

wait_noop() {
    set +o xtrace

    retry=0
    until [ "$(mongo_run "db.getSiblingDB(\"admin\").pbmLock.find().count()" cfg | tail -n 1 | tr -d '\r' )" == 0 ]; do
        sleep 1
        echo -n .
        let retry+=1
        if [ $retry -ge 120 ]; then
            mongo_run "db.getSiblingDB(\"admin\").pbmLock.find()" "cfg"
            exit 1
        fi
    done
    set -o xtrace
}

compare() {
    if [ $1 != $2 ]; then
        echo "$1 doesn't match $2"
        exit 1
    fi
}

compare_arrays() {
    local arr1=$1
    local arr2=$2
    diff=$(diff <(printf "%s\n" "${arr1[@]}") <(printf "%s\n" "${arr2[@]}"))
    if [[ -z "$diff" ]]; then
        echo "OK"
    else
        exit 1
    fi
}

desc() {
    set +o xtrace
    local msg="$@"
    printf "\n\n-----------------------------------------------------------------------------------\n"
    printf "== $msg"
    printf "\n-----------------------------------------------------------------------------------\n\n"
    set -o xtrace
}

start_cluster() {
    local mongo_version=$1

    genMongoKey

    echo 'Build agents and tests'
    docker-compose -f $COMPOSE_PATH build

    if [ ! -d "${test_dir}/docker/backups" ]; then
        mkdir "${test_dir}/docker/backups"
        chmod -R 777 "${test_dir}/docker/backups"
    fi
    export MONGODB_VERSION=${mongo_version:-"4.2"}
    export MONGODB_IMAGE=${MONGODB_IMAGE:-"percona/percona-server-mongodb"}
    docker-compose -f $COMPOSE_PATH up --quiet-pull --no-color -d \
            cfg01 cfg02 cfg03 rs101 rs102 rs103 rs201 rs202 rs203 mongos minio createbucket
    sleep 25
    docker-compose -f $COMPOSE_PATH ps
    export COMPOSE_INTERACTIVE_NO_CLI=1
    docker-compose -f $COMPOSE_PATH exec -T cfg01 /opt/start.sh
    docker-compose -f $COMPOSE_PATH exec -T rs101 /opt/start.sh
    docker-compose -f $COMPOSE_PATH exec -T rs201 /opt/start.sh
    sleep 15
    docker-compose -f $COMPOSE_PATH exec -T mongos mongo mongodb://${BACKUP_USER}:${MONGO_PASS}@localhost /opt/mongos_init.js

    docker-compose -f $COMPOSE_PATH up --quiet-pull --no-color -d \
            agent-cfg01 agent-cfg02 agent-cfg03  agent-rs101 agent-rs102 agent-rs103 agent-rs201 agent-rs202 agent-rs203
}

start_replset() {
    local mongo_version=$1
    local compose=$2

    local nodes="rs101 rs102 rs103 minio createbucket"
    local agents="agent-rs101 agent-rs102 agent-rs103"
    if [ $compose == $COMPOSE_SINGLE_PATH ]; then
        local nodes="rs101 minio createbucket"
        local agents="agent-rs101"
    fi

    genMongoKey

    echo 'Build agents and tests'
    docker-compose -f $compose build

    if [ ! -d "${test_dir}/docker/backups" ]; then
        mkdir "${test_dir}/docker/backups"
        chmod -R 777 "${test_dir}/docker/backups"
    fi

    export MONGODB_VERSION=${mongo_version:-"4.2"}
    export MONGODB_IMAGE=${MONGODB_IMAGE:-"percona/percona-server-mongodb"}
    docker-compose -f $compose up --quiet-pull --no-color -d \
        $nodes

    sleep 25
    docker-compose -f $compose ps
    export COMPOSE_INTERACTIVE_NO_CLI=1
    docker-compose -f $compose exec -T rs101 /opt/start.sh
    sleep 15

    docker-compose -f $compose up -d $agents
}

genMongoKey() {
    key_file="${test_dir}/docker/keyFile"

    if [ ! -f $key_file ]; then
        openssl rand -base64 756 >$key_file
        chmod 400 $key_file
    fi
}

destroy_cluster() {
    local compose=$1

    docker-compose -f $compose ps
    docker-compose -f $compose down -v
}
