#!/bin/bash

GIT_ABS=`git rev-parse --show-toplevel`
RELEASE_DIR=$GIT_ABS/../release/
GIT_BRANCH=`git rev-parse --abbrev-ref HEAD | sed 's|.*/||'`

# Drop to the root of the checkout
cd $GIT_ABS

VERSION=AUTO # -v (version)
PREV_BRANCH=AUTO # -f (from)
PREV_VERSION=AUTO # -F (from version)
NO_UPGRADE=AUTO # -n
IS_PREVIEW=AUTO # -p
TAG_ONLY=NO # -t
BUILD_ONLY=NO # -b
UPGRADE_PREVIEW=NO # -r
SKIP_I18N=NO # -i
SKIP_BUILD_BROWSER_CLIENT=NO # -C
PG_HOST=NONE # -H
PG_USER=NONE # -U
PG_PASS=NONE # -P
PG_PORT=NONE # -O

while getopts ":hv:f:F:nptbriCH:D:U:P:O:" opt; do
    case $opt in
        v)
            VERSION=$OPTARG
        ;;
        f)
            PREV_BRANCH=$OPTARG
        ;;
        F)
            PREV_VERSION=$OPTARG
        ;;
        n)
            NO_UPGRADE=YES
        ;;
        r)
            UPGRADE_PREVIEW=YES
        ;;
        i)
            SKIP_I18N=YES
        ;;
        p)
            IS_PREVIEW=YES
        ;;
        t)
            TAG_ONLY=YES
        ;;
        b)
            BUILD_ONLY=YES
        ;;
        C)
            SKIP_BUILD_BROWSER_CLIENT=YES
        ;;
        H)
            PG_HOST="$OPTARG"
        ;;
        U)
            PG_USER="$OPTARG"
        ;;
        P)
            PG_PASS="$OPTARG"
        ;;
        O)
            PG_PORT="$OPTARG"
        ;;
        \?)
            echo "Invalid Option: -$OPTARG"
            exit 1
        ;;
        :)
            echo "-$OPTARG requires an argument."
            exit 1
        ;;
        h)
            echo "$0 [-v VERSION] [-f PREV_BRANCH | -t | -b] [-F PREV_VERSION] [-n] [-p]"
            echo "   VERSION is auto-detected by default and is based on the currently checked out branch."
            echo "   PREV_BRANCH is auto-detected by default but that isn't reliable. Include remote name!"
            echo "   PREV_VERSION Is auto-detected by default and is based on the PREV_BRANCH's name."
            echo "   -n specifies that you don't want an upgrade script to be auto-generated."
            echo "   -p specifies that this is a preview build."
            echo "   -t turns on tag only mode."
            echo "   -b turns on build only mode."
            echo "   -r prompt to preview upgrade SQL in editor before committing."
            echo "   -i skip i18n; primarily useful for (quickly) testing this script."
            echo "   -C Skip building the browser client. Useful only if all you want to do is generate the DB update script."
            echo "   -H Postgres [H]ostname (optional)"
            echo "   -D Postgres [D]atabase name (optional)"
            echo "   -U Postgres [U]sername (optional)"
            echo "   -P Postgres [P]assword (optional)"
            echo "   -O Postgres p[O]rt"
            echo ""
            echo "   Postgres credentials are used to invoke the EXPERIMENTAL"
            echo "   feature to update the Enhanced Concerto dataset."
            echo ""
            echo "   The provided Pg credentials needs to have permissions to create"
            echo "   databases; using a Pg superuser will be most convenient."
            echo ""
            echo "   The commit created by the process to update the dataset"
            echo "   should be thoroughly reviewed before producing the release."
            echo ""
            echo "   Generally, the update of the Enhanced Concerto dataset should"
            echo "   be done and tested well before the release tarball is built; the main"
            echo "   dependency is when the database schema becomes stable for the"
            echo "   release, particularly changes that add or remove tables or"
            echo "   columns."
            echo ""
            echo "   NOTE: -t and -b override PREV_BRANCH/PREV_VERSION, but -b overrides -t."
            exit -1
        ;;
    esac
done

if [ "$TAG_ONLY" == "YES" ]; then
    PREV_BRANCH="TAG"
fi

if [ "$BUILD_ONLY" == "YES" ]; then
    PREV_BRANCH="PACKAGE"
fi

if [ "$VERSION" == "AUTO" ]; then
    # Auto-pick version based on branch name
    echo AUTO VERSION
    VERSION=`echo $GIT_BRANCH | sed 's/^rel_\([0-9]\+\)_\([0-9]\+\)_\([0-9]\+\)_\(.\+\)$/\1.\2.\3-\4/'`
    VERSION=`echo $VERSION | sed 's/^rel_\([0-9]\+\)_\([0-9]\+\)_\([0-9]\+\)$/\1.\2.\3/'`
    VERSION=`echo $VERSION | sed 's/^rel_\([0-9]\+\)_\([0-9]\+\)_\(.\+\)$/\1.\2-\3/'`
    VERSION=`echo $VERSION | sed 's/^rel_\([0-9]\+\)_\([0-9]\+\)$/\1.\2/'`
    if [ "$VERSION" = "$GIT_BRANCH" ]; then
        echo "AUTO VERSION FAILED."
        exit 1
    fi
fi
SHORT_VERSION=`echo $VERSION | grep -o '^[0-9]\+\.[0-9]\+'`
echo "Version: $VERSION Short: $SHORT_VERSION"

# prep a couple alternate represenations
DASH_VERSION=`echo $VERSION | sed 's/\./-/g'`
SHORT_DASH_VERSION=`echo $SHORT_VERSION | sed 's/\./-/g'`
UNDER_VERSION=`echo $VERSION | sed -e 's/\./_/g;s/-/_/g'`
VERSION_ARRAY=(${VERSION//./ })
PADDED_DECIMAL_VERSION="${VERSION_ARRAY[0]}.$(printf %02d "${VERSION_ARRAY[1]//[!0-9]/}" )$(printf %02d "${VERSION_ARRAY[2]//[!0-9]/}" )"

PREVIEW_TEXT=""

if [ "$IS_PREVIEW" == "YES" ]; then
    PREVIEW_TEXT="previews/"
fi

# Release Preamble
# For adding into README for release builds
# The head is used to check if we have it already (no need to add it twice)
RELEASE_PREAMBLE_HEAD="Preamble: Getting an Evergreen official release tarball"
RELEASE_PREAMBLE=$( cat <<PREAMBLE
$RELEASE_PREAMBLE_HEAD
-------------------------------------------------------

To download and extract the source for the current release of Evergreen, issue
the following commands as the *user* Linux account:

[source, bash]
------------------------------------------------------------------------------
wget -c http://evergreen-ils.org/downloads/${PREVIEW_TEXT}Evergreen-ILS-$VERSION.tar.gz
tar xzf Evergreen-ILS-$VERSION.tar.gz
------------------------------------------------------------------------------

PREAMBLE
)

# This defines what the preamble comes before
RELEASE_PREAMBLE_BEFORE="Preamble: Developer instructions"

if [ "$PREV_BRANCH" != "TAG" -a "$PREV_BRANCH" != "PACKAGE" ]; then
    if [ "$PREV_BRANCH" == "AUTO" ]; then
        echo "AUTO PREVIOUS BRANCH"
        PREV_BRANCH=`echo ${UNDER_VERSION%_*}`
        PREV_BRANCH=`git branch -r | grep "rel_${PREV_BRANCH}_[^_]\+$" | sort -rV | head -n1`
        PREV_BRANCH=`echo $PREV_BRANCH`
        read -p "Does branch $PREV_BRANCH look like the previous version (y/n)?"
        if [ "$REPLY" != "y" -a "$REPLY" != 'Y' ]; then
            echo "Please specify the previous branch as second parameter. To continue auto-version, use AUTO as first parameter."
            exit 1
        fi
    fi
    git show $PREV_BRANCH &>/dev/null
    if [ $? -ne 0 -o -z "$PREV_BRANCH" ]; then
        echo "PREVIOUS VERSION COMMIT NOT FOUND";
        exit 1
    fi
    if [ "$PREV_VERSION" == "AUTO" ]; then
        echo "AUTO PREVIOUS VERSION"
        PREV_BRANCH_END=`echo $PREV_BRANCH | sed 's|.*/||'`
        PREV_VERSION=`echo $PREV_BRANCH_END | sed 's/^rel_\([0-9]\+\)_\([0-9]\+\)_\([0-9]\+\)_\(.\+\)$/\1.\2.\3-\4/'`
        PREV_VERSION=`echo $PREV_VERSION | sed 's/^rel_\([0-9]\+\)_\([0-9]\+\)_\([0-9]\+\)$/\1.\2.\3/'`
        PREV_VERSION=`echo $PREV_VERSION | sed 's/^rel_\([0-9]\+\)_\([0-9]\+\)_\(.\+\)$/\1.\2-\3/'`
        PREV_VERSION=`echo $PREV_VERSION | sed 's/^rel_\([0-9]\+\)_\([0-9]\+\)$/\1.\2/'`
        if [ "$PREV_VERSION" == "$PREV_BRANCH_END" ]; then
            echo "AUTO PREVIOUS VERSION FAILED."
            exit 1
        fi
    fi
    echo "Previous Version: $PREV_VERSION"
else
    echo "Tagging or packaging, no need for previous version"
fi

if [ "$PREV_BRANCH" != "PACKAGE" ]; then

    echo "Applying to Application.pm - HEAD -> $DASH_VERSION"
    echo "Alt: $SHORT_DASH_VERSION -> $DASH_VERSION"
    sed -i -e "s/\"$SHORT_DASH_VERSION[^\"]*\"/\"$DASH_VERSION\"/" -e "s/\"HEAD\"/\"$DASH_VERSION\"/" $GIT_ABS/Open-ILS/src/perlmods/lib/OpenILS/Application.pm
    sed -i "/VERSION/s/'.*'/'$PADDED_DECIMAL_VERSION'/g" Open-ILS/src/perlmods/lib/OpenILS.pm

    echo "Applying to README:"

    if [ "$PREV_BRANCH" != "TAG" ]; then
        if [ "$(grep "$RELEASE_PREAMBLE_HEAD" $GIT_ABS/README )" ]; then
            echo "Updating old download links"
            sed -i -e "s|\(previews/\)\?Evergreen-ILS-.*\.tar\.gz|${PREVIEW_TEXT}Evergreen-ILS-$VERSION.tar.gz|" $GIT_ABS/README
            sed -i -e "s| Evergreen-ILS-.*\.tar\.gz| Evergreen-ILS-$VERSION.tar.gz|" $GIT_ABS/README
        else
            echo "Adding Download Preamble"
            perl -pi -e "s|^|$RELEASE_PREAMBLE\n\n| if /$RELEASE_PREAMBLE_BEFORE/" $GIT_ABS/README
        fi
    fi

    echo "Applying to configure.ac:"
    echo "AC_INIT and AM_INIT_AUTOMAKE entries"
    sed -i -e "s/^\(AC_INIT(Open-ILS, \)[^,]*,/\1$VERSION,/" -e "s/^\(AM_INIT_AUTOMAKE(\[[^]]*], \[\)[^]]*]/\1$VERSION]/" configure.ac

    if [ "$PREV_BRANCH" = "TAG" ]; then
        echo "Committing (but not pushing) the lot of it"
        git commit -asm "Tagging version"
        exit 0;
    fi

    echo "Applying version to 002.schema.config.sql:"
    echo "config.upgrade_log entry for $VERSION"
    sed -i -e "s/\(INSERT INTO config.upgrade_log (version[^)]*) VALUES ('\)[0-9]*\('.*;\).*/&\n\1$VERSION\2/" $GIT_ABS/Open-ILS/src/sql/Pg/002.schema.config.sql;

    if [ "$NO_UPGRADE" == "AUTO" ]; then
        echo "Checking for DB upgrade potential...."
        git ls-tree --name-only $PREV_BRANCH -- Open-ILS/src/sql/Pg/upgrade/ | cut -d/ -f6 | cut -d. -f1 | sort > old_upgrades.txt
        git ls-tree --name-only HEAD -- Open-ILS/src/sql/Pg/upgrade/ | cut -d/ -f6 | cut -d. -f1 | sort > new_upgrades.txt
        UPGRADE_CHECK=`diff old_upgrades.txt new_upgrades.txt | grep '^>' | cut -d' ' -f2`
        UPGRADE_FILE=Open-ILS/src/sql/Pg/version-upgrade/$PREV_VERSION-$VERSION-upgrade-db.sql
        if [ -f "$UPGRADE_FILE" ]; then
            echo "Upgrade script for $PREV_VERSION-$VERSION already exists. Skipping."
            UPGRADE_FILE=""
        else
            echo "Building Upgrade Script."
            echo "--Upgrade Script for $PREV_VERSION to $VERSION" > $UPGRADE_FILE
            echo "\set eg_version '''$VERSION'''" >> $UPGRADE_FILE
            echo "BEGIN;" >> $UPGRADE_FILE
            grep "config.upgrade_log.*$VERSION" Open-ILS/src/sql/Pg/002.schema.config.sql >> $UPGRADE_FILE
            for NUM in $UPGRADE_CHECK; do
                cat Open-ILS/src/sql/Pg/upgrade/$NUM.* 2>/dev/null | grep -v '^\s*\(BEGIN\|COMMIT\);\s*$' >> $UPGRADE_FILE
            done;
            echo "COMMIT;" >> $UPGRADE_FILE
            #Add call to auditor.update_auditors() to keep auditor tables up to date
            echo "" >> $UPGRADE_FILE
            echo "-- Update auditor tables to catch changes to source tables." >> $UPGRADE_FILE
            echo "--   Can be removed/skipped if there were no schema changes." >> $UPGRADE_FILE
            echo "SELECT auditor.update_auditors();" >> $UPGRADE_FILE
            MAYBE_DUPES=`grep -oP 'CREATE (OR REPLACE )?FUNCTION +\K[^ ]*(?= *\()' $UPGRADE_FILE | sort | grep -P '^(.*)\n\1$' | sort -u`
            if [ -n "$MAYBE_DUPES" ]; then
                echo ""
                echo "The following functions may be needlessly duplicated in the upgrade script:"
                echo "$MAYBE_DUPES"
                echo ""
                echo "For reference, I am writing the list to maybe_dupes.txt"
                echo "$MAYBE_DUPES" > maybe_dupes.txt
            fi
            echo ""
            if [ "$UPGRADE_PREVIEW" = "YES" ]; then
                read -p "Please manually check the upgrade file."
                ${EDITOR:-vi} $UPGRADE_FILE
            fi;
            git add $UPGRADE_FILE
        fi
    fi

    echo "Committing (but not pushing) the lot of it"
    COMMIT_MESSAGE="Bumping version numbers"
    if [ -n "$UPGRADE_FILE" ]; then
        COMMIT_MESSAGE="Bumping version numbers and adding Upgrade Script"
    fi
    git commit -asm "$COMMIT_MESSAGE"
    if [ "$PG_HOST" != "NONE" ]; then
        echo "Attempting auto-upgrade for Enhanced Concerto Dataset"
        $GIT_ABS/Open-ILS/src/support-scripts/make_concerto_from_evergreen_db.pl \
        --db-host "$PG_HOST" --db-user "$PG_USER" --db-pass "$PG_PASS" --db-port "$PG_PORT" \
        --output-folder "$GIT_ABS/Open-ILS/tests/datasets/sql/concerto_enhanced" \
        --evergreen-repo "$GIT_ABS" \
        --perform-upgrade \
        --non-interactive

        if [ $? -ne 0 ]; then
            echo "Failed to auto-upgrade the Enhanced Concerto Dataset"
            echo "Proceeding without it"
            read -p "Press [Enter] key to continue"
        else
            echo "Committing Enhanced Concerto Dataset to git"
            COMMIT_MESSAGE="Upgrade Enhanced Concerto Dataset"
            git commit -asm "$COMMIT_MESSAGE"
        fi
    fi
fi

echo "Building release dump"
cd $GIT_ABS
mkdir -p ../release
git archive --prefix=Evergreen-ILS-$VERSION/ HEAD | (cd ../release && tar xf -)
cd ../release/Evergreen-ILS-$VERSION
if [ -f ./autogen.sh ]; then
    echo "Running autogen"
    ./autogen.sh
else
    echo "Running autoreconf"
    autoreconf -i
fi

if [ "$SKIP_I18N" == "NO" ]; then
    cd build/i18n
    echo "Building i18n"
    make install_all_locales
    echo "i18n Cleanup"
    cd ..
    rm -rf i18n
    cd ..
fi;

echo "Installing Dojo"
if [ ! -f "../dojo.tgz" ]; then
    curl -o ../dojo.tgz http://evergreen-ils.org/downloads/dojo.tgz
fi
tar xzf ../dojo.tgz -C Open-ILS/web/js/dojo/

echo "Prepping server download files"

if [ "$SKIP_BUILD_BROWSER_CLIENT" == "NO" ]; then
    # AngularJS staff client
    cd $RELEASE_DIR/Evergreen-ILS-$VERSION
    echo "Building AngularJS browser staff client"
    cd Open-ILS/web/js/ui/default/staff/
    npm install   # fetch build dependencies
    npm run build-prod # copy to build dir and minify JS files
    # npm cache is big and unnecessary in the final build. remove it.
    rm -r node_modules 
    cd ../../../../../ # Open-ILS dir

    # OPAC dependencies
    cd web/opac/deps
    npm install # fetch dependencies
    # and leave them in node_modules; there's no build step
    cd ../../.. # Open-ILS dir

    # Angular staff client
    echo "Building Angular browser staff client"
    cd src/eg2
    npm install   # fetch build dependencies
    ng build --configuration production --localize true
    # npm cache is big and unnecessary in the final build. remove it.
    rm -rf node_modules 
    # similarly, the .angular directory, which includes the build
    # cache, need not be shipped in the release tarball
    rm -rf .angular
else
    echo "Skipping browser client build"
fi

cd $RELEASE_DIR
tar czf Evergreen-ILS-$VERSION.tar.gz Evergreen-ILS-$VERSION/
md5sum Evergreen-ILS-$VERSION.tar.gz > Evergreen-ILS-$VERSION.tar.gz.md5

echo "Removing build directory"
rm -rf Evergreen-ILS-$VERSION/

echo ""
echo "FOR YOU TODO:"
echo "* TEST the release"
if [ "$PREV_BRANCH" != "PACKAGE" ]; then
    echo "* Push release branch"
fi
echo "* Upload files"
echo "* Send emails"
