#! /usr/bin/env bash


###################################################################################
#                                                                                 #
#                   Copyright 2010-2011 Ning, Inc.                                #
#                                                                                 #
#      Ning licenses this file to you under the Apache License, version 2.0       #
#      (the "License"); you may not use this file except in compliance with the   #
#      License.  You may obtain a copy of the License at:                         #
#                                                                                 #
#          http://www.apache.org/licenses/LICENSE-2.0                             #
#                                                                                 #
#      Unless required by applicable law or agreed to in writing, software        #
#      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT  #
#      WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the  #
#      License for the specific language governing permissions and limitations    #
#      under the License.                                                         #
#                                                                                 #
###################################################################################

# set -x

HERE=`cd \`dirname $0\`; pwd`
TOP=$HERE/..

POM="$TOP/pom.xml"

ACTION=
HOST="localhost"
DATABASE="killbill"
USER="root"
PWD="root"
PORT=
PORT_MYSQL=3306
PORT_POSTGRES=5432
DRIVER="mysql"
TEST_ALSO=
OUTPUT_FILE=
DDL_FILE=
CLEAN_FILE=

# Egrep like for skipping some modules until they are ready
SKIP="(server)"


# test if user is running gnu-getopt
TEST=`getopt -o "a:" -l "action:" -- --action dump`
if [ "$TEST" != " --action 'dump' --" ]; then
    echo "You are not using gnu-getopt or latest getopt."
    echo "For Mac OS X, please upgrade 'getopt' to 'gnu-getopt',"
    echo "For Linux, please upgrade 'getopt'."
    exit
fi


ARGS=`getopt -o "a:d:h:u:p:t:f:" -l "action:,driver:,database:,host:,user:,password:,test:,file:,port:,help" -n "db-helper" -- "$@"`
eval set -- "${ARGS}"


function usage() {
    echo -n "./db_helper"
    echo -n " -a|--action <create|clean|dump|migrate|dryRunMigrate|repair|info>"
    echo -n " --driver <mysql|postgres> (default = mysql)"
    echo -n " -h|--host host (default = localhost)"
    echo -n " --port port"
    echo -n " -d|--database database_name (default = killbill)"
    echo -n " -u|--user user_name (default = root)"
    echo -n " -p|--password password (default = root)"
    echo -n " -t|--test (also include test ddl)"
    echo -n " -f|--file file (output file, for dump only)"
    echo -n " --help this message"
    echo
    exit 1
}

function get_modules() {
    local modules=`grep module $POM  | grep -v modules | cut -d '>' -f 2 | cut -d '<' -f 1 | egrep -v "$SKIP"`
    echo $modules
}

function find_test_ddl() {
    local modules=`get_modules`
    local ddl_test=

    local cur_ddl=
    for m in $modules; do
        cur_ddl=`find $TOP/$m/src/test/resources/ -name ddl_test.sql 2>/dev/null`
        ddl_test="$ddl_test $cur_ddl"
    done
    echo "$ddl_test"
}


function find_src_ddl() {
    local modules=`get_modules`
    local ddl_src=

    local cur_ddl=
    for m in $modules; do
        cur_ddl=`find $TOP/$m/src/main/resources/ -name ddl.sql 2>/dev/null`
        ddl_src="$ddl_src $cur_ddl"
    done
    echo "$ddl_src"
}


function create_clean_file() {
    local ddl_file=$1
    local tables=`cat $ddl_file | grep -i "create table" | awk ' { print $3 } '`

    local tmp="/tmp/clean-$DATABASE.$$"
    echo "/*! USE $DATABASE */;" >> $tmp
    echo "" >> $tmp
    for t in $tables; do
        echo "truncate $t;" >> $tmp
    done
    echo $tmp
}


function create_ddl_file() {
    local ddls=`find_src_ddl`
    local test_ddls=
    if [ ! -z $TEST_ALSO ]; then
        test_ddls=`find_test_ddl`
        ddls="$ddls $test_ddls"
    fi

    local tmp="/tmp/ddl-$DATABASE.$$"
    touch $tmp
    if [ $DRIVER == "postgres" ]; then
        cat util/src/main/resources/org/killbill/billing/util/ddl-postgresql.sql > $tmp
    fi
    echo "/*! USE $DATABASE */;" >> $tmp
    echo "" >> $tmp
    for d in $ddls; do
        cat $d >> $tmp
        echo "" >> $tmp
    done
    echo $tmp
}


function create_pgfile() {
    mv -f $HOME/.pgpass $HOME/.pgpass_bak > /dev/null 2>&1
    echo "$HOST:$PORT:*:$USER:$PWD" > $HOME/.pgpass
    chmod 600 $HOME/.pgpass
}


function clean_pgfile() {
    rm -f $HOME/.pgpass > /dev/null 2>&1
    mv -f $HOME/.pgpass_bak $HOME/.pgpass > /dev/null 2>&1
}


function cleanup() {
    rm -f "/tmp/*.$$"
}

function flyway() {
    flyway_bin=util/target/killbill-flyway.jar
    if [ ! -f "$flyway_bin" ]; then
        echo "File $flyway_bin does not exists - build util first"
        usage
    fi

    locations=
    for migration_dir in `find */src/main/resources -type d -name migration`; do
        locations="${locations}filesystem:$migration_dir,"
    done

    java -jar $flyway_bin -locations=$locations -user=$USER -password=$PWD -url=$URL ${@}
}

while true; do
  case "$1" in
    -a|--action) ACTION=$2; shift 2;;
    --driver) DRIVER=$2; shift 2;;
    -d|--database) DATABASE=$2; shift 2;;
    -h|--host) HOST=$2; shift 2;;
    --port) HOST=$2; shift 2;;
    -u|--user) USER=$2; shift 2;;
    -p|--password) PWD=$2; shift 2;;
    -t|--test) TEST_ALSO=1; shift 2;;
    -f|--file) OUTPUT_FILE=$2; shift 2;;
    --help) usage; shift;;
    --) shift; break;;
  esac
done


if [ -z $ACTION ]; then
    echo "Need to specify an action"
    usage
fi


if [ $DRIVER != "mysql" ] && [ $DRIVER != "postgres" ]; then
    echo "Only support driver <mysql> or <postgres>"
    usage
fi


if [ $DRIVER == "mysql" ] && [ -z $PORT ]; then
    PORT=$PORT_MYSQL
fi
if [ $DRIVER == "postgres" ] && [ -z $PORT ]; then
    PORT=$PORT_POSTGRES
fi
if [ $DRIVER == "mysql" ] && [ -z $URL ]; then
    URL=jdbc:mysql://$HOST:$PORT/$DATABASE
fi
if [ $DRIVER == "postgres" ] && [ -z $URL ]; then
    URL=jdbc:postgresql://$HOST:$PORT/$DATABASE
fi


if [ $ACTION == "dump" ]; then
    DDL_FILE=`create_ddl_file`
    if [ -z $OUTPUT_FILE ]; then
        cat $DDL_FILE
    else
        cat $DDL_FILE > $OUTPUT_FILE
    fi
fi


if [ $ACTION == "create" ]; then
    DDL_FILE=`create_ddl_file`
    echo "Applying new schema to database $DATABASE"
    if [ $DRIVER == "mysql" ]; then
        mysql -h $HOST -P $PORT -u $USER --password=$PWD < $DDL_FILE
    else
        create_pgfile
        psql -h $HOST -p $PORT -U $USER -d $DATABASE < $DDL_FILE
        clean_pgfile
    fi
fi


if [ $ACTION == "clean" ]; then
    DDL_FILE=`create_ddl_file`
    CLEAN_FILE=`create_clean_file $DDL_FILE`
    echo "Cleaning db tables on database $DATABASE"
    if [ $DRIVER == "mysql" ]; then
        mysql -h $HOST -P $PORT -u $USER --password=$PWD < $CLEAN_FILE
    else
        create_pgfile
        psql -h $HOST -p $PORT -U $USER -d $DATABASE < $CLEAN_FILE
        clean_pgfile
    fi
fi

if [ $ACTION == "migrate" ] || [ $ACTION == "dryRunMigrate" ] || [ $ACTION == "repair" ] || [ $ACTION == "info" ]; then
    flyway $ACTION
fi

cleanup
