#!/bin/bash

help() {
cat <<HSD
`basename $0` initialises the given database with the OpenQuake schema.
Also, table space paths are created as needed (unless this is turned off
by the user).

!! This will *destroy* all data in the OpenQuake database !!

The command line arguments are as follows:

    --db-name=name      The name of the database to set up.
    --db-port=port      The postgresql server port (default: 5432)
    --db-user=user      Run all commands as this database user [postgres].
    --no-tab-spaces     Don't check/create table spaces and their paths
    --schema-path=path  Absolute path to directory with the schema files.
    --tab-spaces-only   Check/create table spaces and their paths and exit
    --yes               Don't pause for user input, assume yes on all questions
HSD
exit 0
}

if [ $# -eq 0 ]; then
    help
fi

# Openquake version
oq_version="0.5.0"

# Stop at the first error in a batch to give a chance to see the error message
psql_batch_options='--set ON_ERROR_STOP=1'

# Where do the table spaces live?
tspace_path='/var/lib/postgresql/9.1/main/ts'
# What table spaces should be created?
tspace_list="admin eqcat hzrdi hzrdr oqmif riski riskr uiapi"

db_port=5432
schema_path=""
db_name=""
user_interaction="on"
check_table_spaces="on"
table_spaces_only="off"

db_admin_user="postgres"

this_is_linux=0
# Are we running on linux?
if [ -f "`which uname`" ]; then
    os_name=`uname | tr '[:upper:]' '[:lower:]' | cut -f1`
    if [ "$os_name" = "linux" ]; then
        this_is_linux=1
    fi
fi

# What is the name of the db group that all OpenQuake db users belong to?
db_group_name="openquake"

# What OpenQuake db users should be created? The construct below is the bash
# way to assign a heredoc value to a variable BTW.
read -r -d '' db_roles <<'EOF'
opengeo_reader
opengeo_writer
oq_admin
oq_eqcat_reader
oq_eqcat_writer
oq_job_init
oq_job_superv
oq_reslt_writer
EOF

for i in $*
do
    case $i in
    --schema-path=*)
        schema_path=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
        test \( -d "$schema_path" -a -r "$schema_path" \)
        if [ $? -ne 0 ]; then
            echo "!! Schema path $schema_path does not exist or is not readable."
            exit 1
        fi
        ;;
    --db-name=*)
        db_name=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
        ;;
    --db-port=*)
        db_port=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
        ;;
    --db-user=*)
        db_admin_user=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
        ;;
    --no-tab-spaces)
        check_table_spaces="off"
        ;;
    --tab-spaces-only)
        table_spaces_only="on"
        ;;
    -y|--yes)
        user_interaction="off"
        ;;
    -h|--help)
        help
        ;;
    *)
        echo "!! Uknown option: " $i
        exit 2
        ;;
    esac
done

schema_file="$schema_path/openquake.sql"

if [ -z "$db_name" ]; then
    echo "!! Please specify a database name."
    exit 3
fi

if [ "$(id -u)" != "0" ]; then
    echo ""
    echo "!! This script should be run as root."
    if [ "$user_interaction" = "on" ]; then
        echo "!! Press <enter> to continue, or <ctrl>-C to abort"
        read
    fi
fi


if [ "$table_spaces_only" == "off" ]; then
    # None of this is relevant if we only want to check table spaces.
    if [ ! -r $schema_file ]; then
        echo "!! Could not find/read schema file: $schema_file"
        exit 5
    fi

    if [ "$user_interaction" = "on" ]; then
        # Last chance to abort.
        echo '!! This will destroy *ALL* data in the OpenQuake database !!'
        echo 'Press <enter> to continue'
        read
    fi

    # Drop database
    echo ".. Dropping database $db_name .."
    psql -p $db_port -d postgres -U $db_admin_user -c "DROP DATABASE IF EXISTS $db_name"
    # Drop table spaces..
    if [ "$check_table_spaces" == "on" ]; then
        for tspace in $tspace_list; do
            full_ts_name="${tspace}_ts"
            echo ".. Dropping table space $full_ts_name .."
            psql -p $db_port -d postgres -U $db_admin_user -c "DROP TABLESPACE IF EXISTS $full_ts_name"
        done
    fi
else
    check_table_spaces="on"
fi

echo -n ".. Current table spaces: "
echo `psql -p $db_port -U $db_admin_user -c '\db' -d postgres | perl -lane 'if ($_ =~ /^\s\S+/) { print $F[0] unless $. < 3 }'`

if [ "$check_table_spaces" == "on" ]; then
    # Create table spaces if needed.
    for tspace in $tspace_list; do
        full_ts_name="${tspace}_ts"
        full_tspace_path="$tspace_path/$full_ts_name"

        # Create table space path if needed.
        test -d "$full_tspace_path"
        if [ $? -ne 0 ]; then
            echo ".. Creating table space path $full_tspace_path .."
            mkdir -p $full_tspace_path
            if [ $this_is_linux -eq 1 ]; then
                chown -R postgres.postgres $full_tspace_path
            else
                chown -R postgres $full_tspace_path
            fi
        fi

        # Create the actual table space.
        ts_found=`psql -p $db_port -U $db_admin_user -c '\db' -d postgres | perl -lane 'if ($_ =~ /^\s\S+/) { print $F[0] unless $. < 3 }' | grep $full_ts_name | wc -l`
        if [ $ts_found -eq 0 ]; then
            psql -p $db_port -d postgres -U $db_admin_user -c "CREATE TABLESPACE $full_ts_name LOCATION '$full_tspace_path'"
            if [ "$table_spaces_only" == "on" ]; then
                psql -p $db_port -U $db_admin_user -d $db_name -c "DELETE FROM admin.revision_info WHERE artefact = 'openquake/${tspace}'"
                psql -p $db_port -U $db_admin_user -d $db_name -c "INSERT INTO admin.revision_info(artefact, revision, step) VALUES('openquake/${tspace}', '${oq_version}', 0)"
            fi
        fi
    done
fi

if [ "$table_spaces_only" == "on" ]; then
    exit 0
fi

# Starting from here this script is executing many batches
# Stopping as soon as one fails makes the error stand out
set -e

# Create the OpenQuake database
echo ".. Creating database $db_name .."
psql -p $db_port -d postgres -U $db_admin_user -c "CREATE DATABASE $db_name"
createlang -p $db_port -d $db_name -U $db_admin_user plpythonu

postgis="/usr/share/postgresql/9.1/contrib/postgis-1.5"
# Load the PostGIS stuff into the newly created OpenQuake database.
echo ".. Loading postgis functions/data into $db_name .."
psql -p $db_port -U $db_admin_user $psql_batch_options -d $db_name -f $postgis/postgis.sql

psql -p $db_port -U $db_admin_user $psql_batch_options -d $db_name -f $postgis/spatial_ref_sys.sql
psql -p $db_port -U $db_admin_user $psql_batch_options -d $db_name -f /usr/share/postgresql/9.1/contrib/postgis_comments.sql

echo ".. Running schema definition file: $schema_file .."
psql -p $db_port -U $db_admin_user $psql_batch_options -d $db_name -f $schema_file

# Apply database function definitions if present.
functions_file="$schema_path/functions.sql"
if [ -r $functions_file ]; then
    echo ".. Running functions file: $functions_file .."
    psql -p $db_port -U $db_admin_user $psql_batch_options -d $db_name -f $functions_file
fi

# Load static data if present.
load_file="$schema_path/load.sql"
if [ -r $load_file ]; then
    echo ".. Loading static data from: $load_file .."
    psql -p $db_port -U $db_admin_user $psql_batch_options -d $db_name -f $load_file
fi

# Apply database schema/table comments if present.
comments_file="$schema_path/comments.sql"
if [ -r $comments_file ]; then
    echo ".. Running comments file: $comments_file .."
    psql -p $db_port -U $db_admin_user $psql_batch_options -d $db_name -f $comments_file
fi

# Create OpenQuake database group if not present.
oq_group_present=`psql -p $db_port -U $db_admin_user -c '\dg' -d postgres | perl -lane 'if ($_ =~ /^\s\S+/) { print $F[0] unless $. < 3 }' | grep $db_group_name | wc -l`
if [ $oq_group_present -eq 0 ]; then
    psql -p $db_port -d postgres -U $db_admin_user -c "CREATE ROLE $db_group_name"
fi

# Create OpenQuake database users/roles if/as needed.
for role in $db_roles; do
    role_present=`psql -p $db_port -U $db_admin_user -c '\dg' -d postgres | perl -lane 'if ($_ =~ /^\s\S+/) { print $F[0] unless $. < 3 }' | grep $role | wc -l`
    if [ $role_present -eq 0 ]; then
        psql -p $db_port -d postgres -U $db_admin_user -c "CREATE ROLE $role WITH LOGIN IN GROUP openquake"
    fi
done

# Apply database security settings if present.
security_file="$schema_path/security.sql"
if [ -r $security_file ]; then
    echo ".. Running security settings file: $security_file .."
    psql -p $db_port -U $db_admin_user $psql_batch_options -d $db_name -f $security_file
fi

# Apply database table indexes if present.
indexes_file="$schema_path/indexes.sql"
if [ -r $indexes_file ]; then
    echo ".. Applying index definitions: $indexes_file .."
    psql -p $db_port -U $db_admin_user $psql_batch_options -d $db_name -f $indexes_file
fi
