#!/bin/bash

source $OPENSHIFT_CARTRIDGE_SDK_BASH

export STOPTIMEOUT=10

# Run mysql commands
function run_sql {
  echo "$@" | /usr/bin/mysql -h $OPENSHIFT_MYSQL_DB_HOST -P $OPENSHIFT_MYSQL_DB_PORT -u $OPENSHIFT_MYSQL_DB_USERNAME --password="$OPENSHIFT_MYSQL_DB_PASSWORD" --skip-column-names
}

function is_running {
  pidfile=$OPENSHIFT_MYSQL_DIR/pid/mysql.pid

  if [ -f $pidfile ]; then
    mysql_pid=`cat $pidfile 2> /dev/null`
    myid=`id -u`

    if `ps --pid $mysql_pid > /dev/null 2>&1` || `pgrep -x mysqld_safe -u $myid > /dev/null 2>&1`
    then
      return 0
    fi
  fi

  return 1
}

# TODO: account for standalone scenario
# TODO: source user hooks?
# Start mysqld and block until it comes up.
function start {
  if ! is_running; then
    /usr/bin/mysqld_safe --defaults-file=$OPENSHIFT_MYSQL_DIR/conf/my.cnf > /dev/null 2>&1 &    
    wait_for_mysqld_availability
  else
    echo "MySQL already running" 1>&2
  fi
}

function wait_for_mysqld_availability {
  for i in {1..30}; do
    is_running && return 0
    sleep 1
  done
  return 1
}

function stop {
  if is_running; then
    pidfile=$OPENSHIFT_MYSQL_DIR/pid/mysql.pid

    if [ -f $pidfile ]; then
      pid=$( /bin/cat $pidfile )
      /bin/kill $pid
      ret=$?
      if [ $ret -eq 0 ]; then
        TIMEOUT="$STOPTIMEOUT"
        while [ $TIMEOUT -gt 0 ] && [ -f "$pidfile" ]
        do
          /bin/kill -0 "$pid" >/dev/null 2>&1 || break
          sleep 1
          let TIMEOUT=${TIMEOUT}-1
        done
      fi
    else
      if `pgrep -x mysqld_safe > /dev/null 2>&1`; then
        echo "Warning: MySQL process exists without a pid file.  Use force-stop to kill." 1>&2
      else
          echo "MySQL already stopped" 1>&2
      fi
    fi
  fi
}

function status {
  if is_running; then
    client_result "MySQL is running" 
  else
    client_result "MySQL is stopped" 
  fi

  exit 0
}

function pre_snapshot {
  # TODO: add support for scalable apps, where DB is not located on primary gear
  start

  echo "$OPENSHIFT_MYSQL_DB_USERNAME" > $OPENSHIFT_DATA_DIR/mysql_db_username
  echo "$OPENSHIFT_MYSQL_DB_HOST" > $OPENSHIFT_DATA_DIR/mysql_db_host
  echo "$OPENSHIFT_APP_NAME" > $OPENSHIFT_DATA_DIR/mysql_db_dbname

  dump_file=$OPENSHIFT_DATA_DIR/mysql_dump_snapshot.gz
  local db_host=$OPENSHIFT_MYSQL_DB_HOST
  local db_port=$OPENSHIFT_MYSQL_DB_PORT

  {
    /usr/bin/mysqldump --extended-insert --quick -h $db_host -P $db_port -u $OPENSHIFT_MYSQL_DB_USERNAME --password="$OPENSHIFT_MYSQL_DB_PASSWORD" --all-databases --add-drop-table | /bin/gzip > $dump_file
  } ||
  {
    warning "Couldn't not dump mysql! Continuing anyway"
    /bin/rm -rf $OPENSHIFT_DATA_DIR/mysql_dump_snapshot.gz
  }

  stop
}

function post_snapshot {
  true
}

function pre_restore {
  cleanup_dump
}

function post_restore {
  # Ensure a snapshot file exists
  if [ -f $OPENSHIFT_DATA_DIR/mysql_dump_snapshot.gz ]; then
    start

    # Restore stashed variables and get current variables
    OLD_IP=$(< $OPENSHIFT_DATA_DIR/mysql_db_host)
    NEW_IP=$OPENSHIFT_MYSQL_DB_HOST
    OLD_NAME=$(< $OPENSHIFT_DATA_DIR/mysql_db_dbname)
    NEW_NAME=$OPENSHIFT_APP_NAME

    if [ -s $OPENSHIFT_DATA_DIR/mysql_db_username ]; then
      OLD_USER=$(< $OPENSHIFT_DATA_DIR/mysql_db_username)
    else
      OLD_USER="admin"
    fi
    NEW_USER=$OPENSHIFT_MYSQL_DB_USERNAME

    # Drop and recreate current database
    # Need to use backticks here to make sure name is properly escaped
    run_sql "DROP DATABASE IF EXISTS \`$NEW_NAME\`;" || error "Could not drop existing database" 187
    run_sql "CREATE DATABASE \`$NEW_NAME\`;" || error "Could not create database" 187

    # Restore the old database verbatim, this will be using the old database name
    # Pipe this command directly to mysql instead of using run_sql so that we don't have to create a massive string to hold the sql dump file
    # TODO: Ideally this would pipe directly into run_sql, but I have yet to get it to work
    {
      (
        echo "SET AUTOCOMMIT=0;"
        echo "SET UNIQUE_CHECKS=0;"
        echo "SET FOREIGN_KEY_CHECKS=0;"
        /bin/zcat $OPENSHIFT_DATA_DIR/mysql_dump_snapshot.gz
        echo "SET FOREIGN_KEY_CHECKS=1;"
        echo "SET UNIQUE_CHECKS=1;"
        echo "SET AUTOCOMMIT=1;"
        echo "COMMIT;"
      ) | /usr/bin/mysql -h $OPENSHIFT_MYSQL_DB_HOST -P $OPENSHIFT_MYSQL_DB_PORT -u $OPENSHIFT_MYSQL_DB_USERNAME --password="$OPENSHIFT_MYSQL_DB_PASSWORD" --skip-column-names
    } || error "Could not import MySQL Database" 187


    # Grant permissions to the current user
    run_sql "
    GRANT ALL ON *.* TO '$NEW_USER'@'$NEW_IP' IDENTIFIED BY '$OPENSHIFT_MYSQL_DB_PASSWORD' WITH GRANT OPTION;
    GRANT ALL ON *.* TO '$NEW_USER'@'localhost' IDENTIFIED BY '$OPENSHIFT_MYSQL_DB_PASSWORD' WITH GRANT OPTION;
    " || error "Could not grant permissions for MySQL database" 187

    # Only run the following if the username is different
    if [ "${OLD_USER}" != "${NEW_USER}" ]
    then
      # Remove the user from any grants that it has
      {
        for host in $(run_sql "SELECT Host from mysql.user WHERE user.user='${OLD_USER}'")
        do
          run_sql "DROP USER \`$OLD_USER\`@'${host}';" || warning "Could not drop old user" 187
        done
      }
    fi

    # Refresh the privileges
    run_sql "FLUSH PRIVILEGES;" || error "Could not flush privileges" 187

    # Only run the following if the database name has changed
    if [ "${OLD_NAME}" == "${NEW_NAME}" ]
    then
      warning "Old and new names are the same, no need to rename"
    else
      # Dump the old database and restore it into the new database
      # This approach provides relational consistency and will work with tables, views, triggers, etc
      # TODO: This may not work if the user created another database that has references to this database
      {
        /usr/bin/mysqldump -h $NEW_IP -P $OPENSHIFT_MYSQL_DB_PORT -u $NEW_USER --password="$OPENSHIFT_MYSQL_DB_PASSWORD" $OLD_NAME | \
          mysql -h $NEW_IP -P $OPENSHIFT_MYSQL_DB_PORT -u $NEW_USER --password="$OPENSHIFT_MYSQL_DB_PASSWORD" $NEW_NAME
      } || error "Could not rename database" 187

      # Drop the old database now that the data has been preserved
      run_sql "DROP DATABASE \`$OLD_NAME\`;" || error "Could not drop old database" 187
    fi

    cleanup_dump
  else
    echo "MySQL restore attempted but no dump found!" 1>&2
    echo "$OPENSHIFT_DATA_DIR/mysql_dump_snapshot.gz does not exist" 1>&2
  fi
}

function cleanup_dump {
  rm -f $OPENSHIFT_DATA_DIR/mysql_dump_snapshot.gz
  rm -f $OPENSHIFT_DATA_DIR/mysql_db_host
  rm -f $OPENSHIFT_DATA_DIR/mysql_db_username
  rm -f $OPENSHIFT_DATA_DIR/mysql_db_dbname
}

case "$1" in
  start)
    start
  ;;
  stop)
    stop
  ;;
  status)
    status
  ;;
  restart)
    stop
    start
  ;;
  pre-snapshot)
    pre_snapshot
  ;;
  post-snapshot)
    post_snapshot
  ;;
  pre-restore)
    pre_restore
  ;;
  post-restore)
    post_restore
  ;;
esac
