#!/bin/sh

SLEEP=10
PRINT=false
CALCULATE=false
REDRAW=false
SILENT=false
EXIT_ON_ERROR=false
WATCH=false
MYSQL_HOST="localhost"
COMPARE_TYPE="eq"
COMMAND=""
COMMAND_NOK=""

usage() {
    printf "$0 [options] <query> <target>\n"
    printf "  -H <host>         Mysql host\n"
    printf "  -u <user>         Mysql user\n"
    printf "  -d <database>     Mysql database\n"
    printf "  -t <compare_type> eq, lt or gt, defaults to eq\n"
    printf "  -n <frequency>    How often to run sql query\n"
    printf "  -c <command>      Command to run when target is reached\n"
    printf "  -l <command>      Command to run when target is no longer reached, but has been reached\n"
    printf "  -w                Watch mode, this will stop the program from exiting when target is reached,\n"
    printf "                    but continue to run command each time criteria is triggered. \n"
    printf "  -p                Print the current value for each check\n"
    printf "  -P                Print only on same line (also enables -p)\n"
    printf "  -k                C(k)alculate estimation until target\n"
    printf "  -s                Silent mode, print only minimal info\n"
    printf "  -e                Exit on error\n"
}

while getopts "H:u:d:c:t:n:l:pPewkhs" opt; do
  case ${opt} in
    H )
      MYSQL_HOST="$OPTARG"
      ;;
    u )
      MYSQL_USER="$OPTARG"
      ;;
    d )
      MYSQL_DATABASE="$OPTARG"
      ;;
    t )
      COMPARE_TYPE="$OPTARG"
      ;;
    n )
      SLEEP="$OPTARG"
      ;;
    c )
      COMMAND="$OPTARG"
      ;;
    l )
      COMMAND_NOK="$OPTARG"
      ;;
    p )
      PRINT=true
      ;;
    P )
      PRINT=true
      REDRAW=true
      ;;
    w )
      WATCH=true
      ;;
    k )
      CALCULATE=true
      ;;
    s )
      SILENT=true
      ;;
    e )
      EXIT_ON_ERROR=true
      ;;
    h )
      usage
      exit 0
      ;;
    \? )
      echo "Invalid option: $OPTARG" 1>&2
      exit 1
      ;;
    : )
      echo "Option -$OPTARG requires an argument." 1>&2
      exit 1
      ;;
  esac
done
shift $((OPTIND -1))

if [ -z "$1" ]; then
  echo "Error: <query> argument is missing." >&2
  usage
  exit 1
fi
QUERY="$1"

if [ -z "$2" ]; then
  echo "Error: <target> argument is missing." >&2
  usage
  exit 1
fi
TARGET="$2"

if [ -z "$MYSQL_HOST" ]; then
  echo "Error: -H <host> argument is missing." >&2
  usage
  exit 1
fi

if [ -z "$MYSQL_USER" ]; then
  echo "Error: -u <user> argument is missing." >&2
  usage
  exit 1
fi

if [ -z "$MYSQL_DATABASE" ]; then
  echo "Error: -d <database> argument is missing." >&2
  usage
  exit 1
fi

PWD_SET_HERE=false
if [ -z "$MYSQL_PWD" ]; then
    read -s -p "Enter password: " MYSQL_PWD
    echo
    export MYSQL_PWD
    PWD_SET_HERE=true
fi

TARGET_OK=false
LAST=0
ELAPSED_TIME=0
LAST_CHANGE=0

while true; do
    RESULT=$(mysql -u"$MYSQL_USER"  -h"$MYSQL_HOST" "$MYSQL_DATABASE" -e "$QUERY" --batch --silent)
    if [ ! "$?" = "0" ]; then
        tput setaf 1
        >&2 echo "[$(date)]: MySQL Error!"
        tput sgr0
        if [ "$EXIT_ON_ERROR" = true ]; then
            exit 1
        fi
        TARGET_OK=false
        sleep $SLEEP
        continue
    fi

    if [ "$PRINT" = true ]; then
        if [ "$REDRAW" = true ]; then
            tput cr
            tput el
        fi
        if [ "$SILENT" = false ]; then
            printf "[$(date)]: "
        fi
        printf "${RESULT}"
        if [ "$CALCULATE" = true ]; then
            CHANGE=$(python -c "print(int(abs($RESULT-$LAST)))" 2> /dev/null)
            ELAPSED_TIME=$(($ELAPSED_TIME+$SLEEP))
            LAST=$RESULT

            if [ $CHANGE -ne 0 ]; then
                remaining_time=$(( (TARGET - RESULT) * ELAPSED_TIME / CHANGE ))
                remaining_time=$(python -c "print(abs($remaining_time))")
                LAST_CHANGE=$CHANGE
            fi

            EST=$(($(date +%s)+$remaining_time))
            printf " ~ $LAST_CHANGE/s ETA $(date -d @$EST) "
            tput bold
            printf "[$(date -u +"%T" -d "@${remaining_time}")]"
            tput sgr0
        fi
        if [ ! "$REDRAW" = true ]; then
            printf "\n"
        fi
    fi

    _TARGET_OK=false
    if [ "$COMPARE_TYPE" = "eq" ]; then
        if [ "$RESULT" = "$TARGET" ]; then
            _TARGET_OK=true
            SIGN_OK="="
            SIGN_NOK="="
        fi
    elif [ "$COMPARE_TYPE" = "lt" ]; then
        if (( RESULT < TARGET )); then
            _TARGET_OK=true
            SIGN_OK=">"
            SIGN_NOK="<"
        fi
    elif [ "$COMPARE_TYPE" = "gt" ]; then
        if (( RESULT > TARGET )); then
            _TARGET_OK=true
            SIGN_OK="<"
            SIGN_NOK=">"
        fi
    fi

    if [ "$_TARGET_OK" = true ]; then
        if [ "$TARGET_OK" = false ]; then
            if [ "$SILENT" = false ]; then
                if [ "$PRINT" = true ]; then
                    printf "[$(date)]: Target "
                    tput setaf 2
                    printf "OK  "
                    tput sgr0
                    tput sitm
                    printf "$TARGET "
                    tput ritm
                    printf "$SIGN_OK "
                    tput bold
                    printf "$RESULT\n"
                    tput sgr0
                fi
            fi
            if [ ! "$COMMAND" = "" ]; then
                sh -c "$COMMAND"
            fi
        fi
        TARGET_OK=true

        if [ "$WATCH" = false ]; then
            break
        fi
    else
        if [ "$TARGET_OK" = true ]; then
            if [ "$SILENT" = false ]; then
                if [ "$PRINT" = true ]; then
                    printf "[$(date)]: Target "
                    tput setaf 1
                    printf "NOK "
                    tput sgr0
                    tput sitm
                    printf "$TARGET "
                    tput ritm
                    printf "$SIGN_NOK "
                    tput bold
                    printf "$RESULT\n"
                    tput sgr0
                fi
            fi
            if [ ! "$COMMAND_NOK" = "" ]; then
                sh -c "$COMMAND_NOK"
            fi
        fi
        TARGET_OK=false
    fi

    sleep $SLEEP
done

if [ "$PWD_SET_HERE" = true ]; then
    unset MYSQL_PWD
fi
