#!/bin/bash

PATH=$PATH:/usr/lib/ruby/bin

if [ -z "$1" ]; then
   echo "ERROR: command is't defined"  >&2
   exit 1
fi

if [ -z "$2" ]; then
   echo "ERROR: name of the rails application isn't defined"  >&2
   exit 2
fi

method=$1
name=$2
cmd=$3

libexecdir=/usr/lib
datadir=/var/lib
srcdir=$libexecdir/$name
rootdir=$datadir/$name
confdir=/etc/$name
cachedir=/var/cache/$name
logdir=/var/log/$name
wwwdir=/var/www/$name

[ -n $(id -u _$name 2>/dev/null) ] && user=_$name
if [ -f "/var/spool/$name/tmp" ]; then
   tmpdir=/var/spool/$name/tmp
else
   tmpdir=/var/tmp/$name
fi

export RAILS_ENV=production
export RAKE_ENV=production

function setup {
   cd $rootdir
   echo "Work dir is '$rootdir'"

   echo "Processing rails application '$name' setup..."

   # Apply variables if any
   if [ -f "/etc/sysconfig/$name" ]; then
      echo "Applying variables from '/etc/sysconfig/$name'"
      # source "/etc/sysconfig/$name"
      IFS=$'\n'; for line in $(cat /etc/sysconfig/$name); do export $line 2>/dev/null ; done
   fi

   # Add the "$name" user and group
   getent group $name >/dev/null || groupadd -r $name
   getent passwd _$name >/dev/null || \
   useradd -r -g $name -G $name -d $rootdir -s /bin/bash -c "$name" _$name

   #validate postgresdb
   #%post_service postgresql

   mkdir -m 750 -p $tmpdir/pids $tmpdir/sockets $cachedir/_ $wwwdir
   rm -rf $tmpdir/cache
   ln -sf $cachedir/_ $tmpdir/cache
   chown $user:$name $tmpdir $cachedir $tmpdir/cache $wwwdir -R

   # reconstruct code tree
   if [ ! -f $datadir/Gemfile ]; then
     ls $srcdir | while read f; do
       [ -L "$rootdir/$f" ] || ln -sf "$srcdir/$f" "$rootdir/$f" 2>/dev/null
     done
   fi

   # reconstruct public web tree if any
   if [ -d $srcdir/public -a -d $wwwdir ]; then
     ls $srcdir/public | while read f; do
       [ -L "$wwwdir/$f" ] || ln -sf "$srcdir/public/$f" "$wwwdir/$f" 2>/dev/null
     done
   fi

   # restore broken links if any
   find /usr/lib/foreman/ -xtype l -not -regex ".*\(node_modules\|config\).*" | while read -r f; do
     tgt=$(readlink "$f")
     mkdir -p "$tgt"
     chown $user:$name "$tgt"
   done

   # CONFDIR=/etc
   # alias bundle exec rake='bundle exec rake'

   if [ -z "$(psql -U postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='$user'")" ]; then
      # create db user with postgres
      createuser $user -U postgres --createdb -w
   fi

   # env
   echo "Renewing dependencies..."
   rm -f Gemfile.lock
   rails_env="RAILS_ENV=$RAILS_ENV BUNDLE_GEMFILE=${rootdir}/Gemfile GEM_HOME=/var/cache/ruby/gemie"
   su - $user -c "$rails_env bundle install --without development test" > $logdir/bundle.log 2>&1 || true
   su - $user -c "$rails_env bundle update" >> $logdir/bundle.log 2>&1 || return 3
   # bundle binstubs bundler --force
   # npm install

   # secret token used for cookie signing etc.
   if [ ! -L $datadir/$name/config/initializers/local_secret_token.rb -o \
        -z "$(cat $confdir/local_secret_token.rb 2> /dev/null)" ]; then
      echo "Initializing secret..."
      [ -L $datadir/$name/config/initializers/local_secret_token.rb ] || \
         ln -sf $confdir/local_secret_token.rb \
                $datadir/$name/config/initializers/local_secret_token.rb
      su - $user -c "$rails_env bundle exec rake security:generate_token" >> $logdir/generators.log 2>&1 || return 4
      chmod 0640 $confdir/local_secret_token.rb
      chown $user:$name $confdir/local_secret_token.rb
   fi

   # encryption key used to encrypt DB contents
   # move the generated key file to /etc/$name/ so users back it up, symlink to it from ~$name
   #if [ ! -L $datadir/$name/config/initializers/encryption_key.rb -o \
   #     -z "$(cat $confdir/encryption_key.rb 2> /dev/null)" ]; then
   #   echo "Initializing encryption key..."
   #   [ -L $datadir/$name/config/initializers/encryption_key.rb ] || \
   #      ln -sf $confdir/encryption_key.rb \
   #             $datadir/$name/config/initializers/encryption_key.rb
   #   su - $user -c "$rails_env bundle exec rake security:generate_encryption_key" >> $logdir/generators.log 2>&1 || return 5
   #   chmod 0640 $confdir/encryption_key.rb
   #   chown $user:$name $confdir/encryption_key.rb
   #fi

   if ! psql -U postgres -lqt | cut -d \| -f 1 | grep -qw ${name}_${RAILS_ENV}; then
      echo "Initializing database..."
      dbname=$(ruby -ryaml -rerb -e "puts ERB.new(YAML.load(IO.read('$confdir/database.yml'))['production']['database']).result")
      createdb -U $user $dbname >> $logdir/db_setup.log 2>&1 || return 6
      # su - $user -c "$rails_env bundle exec rake db:create" >> $logdir/db_setup.log 2>&1 || return 6
   fi

   echo "Checking migration and seeds..."
   # We need to run the db:migrate after the install transaction
   # always attempt to reencrypt after update in case new fields can be encrypted
   su - $user -c "$rails_env bundle exec rake db:migrate db:encrypt_all db:compute_resources:encrypt" >> $logdir/db_setup.log 2>&1 || return 7
   su - $user -c "$rails_env bundle exec rake db:seed" >> $logdir/db_setup.log 2>&1 || return 8

   #echo "Generating API cache..."
   #su - $user -c "$rails_env bundle exec rake apipie:cache:index" >> $logdir/apipie_cache.log 2>&1 || return 9

   # -z "$(ls ./public/webpack/*.js 2>/dev/null)" -a \
   #if [ -n "$(bundle exec rake -T 2>/dev/null |grep webpack:compile)" ]; then
   #   echo "Initializing webpack frontend..."
   #   su - $user -c "$rails_env bundle exec rake webpack:compile" >> $logdir/webpack_compile.log 2>&1 || return 11
   #fi

   # compile always
   #if [ -n "$(bundle exec rake -T 2>/dev/null |grep assets:precompile)" ]; then
   #   echo "Initializing assets frontend..."
   #   su - $user -c "$rails_env bundle exec rake assets:precompile" >> $logdir/assets_precompile.log 2>&1 || return 12
   #fi

   # compile locales
   #if [ -n "$(bundle exec rake -T 2>/dev/null |grep po_to_json)" ]; then
   #   echo "Compiling locales..."
   #   su - $user -c "$rails_env bundle exec rake locale:po_to_json" >> $logdir/locale_compile.log 2>&1 || return 13
   #fi

   echo "Cleaning..."
   su - $user -c "$rails_env bundle exec rake tmp:clear" >> $logdir/tmp_clear.log 2>&1 || return 10

   # display password
   grep "Login credentials" /var/log/foreman/ -r | sed "s,.*:Log,Log," | tail -1

   chown $user:$name $logdir/*.log -R 2>/dev/null
   chown $user:$name $tmpdir -R 2>/dev/null
   chown $user:$name Gemfile.lock 2>/dev/null

   return 0
}

function cleanup {
   echo "Cleaning up..."

   rm -rf $cachedir/_/* $tmpdir/* $rootdir/* $wwwdir/*
}

function mrproper {
   cd $rootdir
   echo "Work dir is '$rootdir'"

   echo "Trying stop service..."
   systemctl stop $name

   echo "Dropping DB..."
   DISABLE_DATABASE_ENVIRONMENT_CHECK=1 \
      bundle exec rake db:drop >> $logdir/db_setup.log 2>&1 || return 13

   cleanup

   cd $HOME
   echo "Try removing package..."
   apt-get remove $name <<< "y" >> $logdir/setup.log 2>&1 || return 14

   echo "MrPropering..."
   rm -rf $rootdir
   dropuser $name -U postgres
   groupdel -f $name
   userdel -rf _$name
}

function run {
   cd $rootdir
   echo "Running command '$@' in work dir '$rootdir'..."

   bundle exec "$@" 2>$logdir/run_errors.log || (
      rm -f Gemfile.lock
      bundle --without=development,test > $logdir/bundle.log 2>&1 || return 3
      bundle exec "$@" 2>$logdir/run_errors.log )
}

case "$method" in
   setup)
      setup
      ;;
   cleanup)
      cleanup
      ;;
   mrproper)
      mrproper
      ;;
   run)
      if [ -z "$cmd" ]; then
         echo "ERROR: command to run the rails application isn't defined"  >&2
         exit 13
      fi
      shift
      shift

      run "$@"
      ;;
esac

code=$?

if (( code != 0 )); then
   echo "Error code is: $code"
fi

exit $code
