#!/bin/bash

route_prefix=medical_check

# Any failure causes exit
set -eE -o functrace

report_failure() {
  local lineno=$2
  local fn=$3
  local exitstatus=$4
  local msg=$5
  local lineno_fns=${1% 0}
  if [[ $lineno_fns != "0" ]] ; then
    lineno="${lineno} ${lineno_fns}"
  fi
  if [[ $exitstatus == 0 ]] ; then
    echo "${BASH_SOURCE[1]}: Finished!"
  else
    echo "${BASH_SOURCE[1]}:${fn}[${lineno}] Failed with status ${exitstatus}: $msg"
  fi
}

trap 'report_failure "${BASH_LINENO[*]}" "$LINENO" "${FUNCNAME[*]:-script}" "$?" "$BASH_COMMAND"' ERR


case "$1" in
[0-9]*)
    export BUNDLE_GEMFILE=$PWD/test/rails_$1.gemfile
    ;;
esac
while :
do
    case "$BUNDLE_GEMFILE" in
    */test/rails_[Qq].gemfile)
        echo "Aborting..."
        exit 2
        ;;
    */test/rails_edge.gemfile|*/test/rails_[0-9].[0-9]*.gemfile)
        if [ -f "$BUNDLE_GEMFILE" ]; then
            break
        fi
        ;;
    esac
    echo "== SELECT GEMFILE =="
    echo
    echo "Please select the gemfile for the required rails series:"
    (cd test ; ls rails*gemfile | ruby -p -e '$_.sub!(/rails_(.*).gemfile/, "    \\1")' )
    echo
    echo -n "Enter choice (or q to quit): "
    read x
    export BUNDLE_GEMFILE=$PWD/test/rails_$x.gemfile
done

if [ -z  "$MIDDLEWARE" ]; then
  echo -n "Add as middleware [N/y] : "
  read MIDDLEWARE
  export MIDDLEWARE
fi
rm -rf tmp/Gemfile* tmp/railsapp tmp/bin tmp/gems test/bin test/rails*.gemfile.lock

mkdir -p tmp/gems

. test/init_variables

if $rbenv_which bundle ; then
  echo Bundler is installed
else
  gem install bundler ${BUNDLER_VERSION:+-v ${BUNDLER_VERSION}}
  $rehash
fi

echo "Running bundle with BUNDLE_GEMFILE=$BUNDLE_GEMFILE ..."
if ! smarter_bundle ; then
    echo "Test aborted (missing required gems)"
    exit 2
elif [ ! -s $BUNDLE_GEMFILE.lock ] ; then
    echo "Error: smarter_bundler return OK status BUT lock file ($BUNDLE_GEMFILE.lock) is missing!"
    exit 3
else
    echo bundle passed - lock file contains:
    cat $BUNDLE_GEMFILE.lock
    echo
fi
$rehash

rails="$base_dir/test/bin/rails"
rake="$base_dir/test/bin/rake"

echo Checking $rails is present ...
[ -f $rails -a -f $rake ] || bundle ${BUNDLER_VERSION:+_${BUNDLER_VERSION}_} exec rake rails:update:bin || echo '(ignored rake rails:update:bin exit status)'
[ -f $rails ] || bundle ${BUNDLER_VERSION:+_${BUNDLER_VERSION}_} binstubs railties || echo '(ignored bundle exit status)'
[ -f $rails ] || bundle ${BUNDLER_VERSION:+_${BUNDLER_VERSION}_} binstubs rails || echo '(ignored bundle exit status)'
if [ ! -f $rails ]; then
    echo "Test aborted (unable to create $rails)"
    exit 2
fi

if [ ! -f $rake ]; then
    echo "Running bundle binstubs rake ..."
    if ! bundle ${BUNDLER_VERSION:+_${BUNDLER_VERSION}_} binstubs rake || [ ! -f $rake ]; then
        echo "Test aborted (unable to create $rake)"
        exit 2
    fi
fi

actual_rails_version=`$rails -v`

[ -d lib/health_check ] || exec echo setup_railsapp MUST be executed in the base of the health_check gem/clone of git repository

export GEM_PATH="$tmp_dir/gems:`gem environment gempath`"
echo Set GEM_PATH=$GEM_PATH

echo Installing health_check as a gem into $tmp_dir/gems
rm -f pkg/health_check-*.gem
if env GEM_HOME=$tmp_dir/gems $rake install
then
    echo rake install passed
else
    echo rake install failed! running gem install pkg/health_check-*.gem manually to see error message:
    env GEM_HOME=$tmp_dir/gems gem install pkg/health_check-*.gem
    echo gem install worked, but flagging it as a FAIL anyway since rake install failed!
    exit 2
fi

echo Gems in tmp/gems:
ls tmp/gems

echo Environment:
env | egrep 'TRAVIS|RAILS|RUBY|_ENV|GEM|BUNDLE' || echo "No relevant variables set"

cd $tmp_dir

case `ruby -e 'puts JRUBY_VERSION' 2> /dev/null` in
    [0-9]*)
        db=jdbcsqlite3
        # Appears to need a bit extra time
        ;;
    *)
        db=sqlite3
        ;;
esac

echo "Creating $actual_rails_version app in $tmp_dir/railsapp using adapter $db"
case "$actual_rails_version" in
    *' '[345].*)
        args="--skip-bundle -d $db"
        case "$BUNDLE_GEMFILE" in
        *rails_edge.gemfile)
            $rails new railsapp $args --edge
            ;;
        *)
            $rails new railsapp $args
            ;;
        esac
        ;;
    *' '[6].*)
        args="--skip-bundle -d $db --skip-git --skip-bootsnap"
        case "$BUNDLE_GEMFILE" in
        *rails_edge.gemfile)
            $rails new railsapp $args --edge
            ;;
        *)
            $rails new railsapp $args
            ;;
        esac
        ;;
    *)
        echo "Unknown rails version"
        ;;
esac

cd $railsapp

[ -z "$rehash" ] || rbenv local `rbenv version-name`

echo "Changed current directory to railsapp root: $railsapp"

echo "Fixing rdoc require in Rakefile if needed"
ruby -p -i.bak -e '$_.gsub!(/rake.rdoctask/, "rdoc/task")' Rakefile

echo "Configuring mailer to point to fake_smtp_server port 3555"
cat >> config/environment.rb <<'!EOF!'

ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = { address: "localhost", port: 3555 }

!EOF!

echo Adding an initializer for health_check gem ...
mkdir -p config/initializers
tee config/initializers/health_check.rb <<!
require 'fileutils'

if defined? HealthCheck
  HealthCheck.setup do |config|
    config.success = "$success"
    config.smtp_timeout = 60.0
    config.http_status_for_error_text = 550
    config.http_status_for_error_object = 555
    config.uri = '$route_prefix'
    config.origin_ip_whitelist = ENV['IP_WHITELIST'].split(',') unless ENV['IP_WHITELIST'].blank?
    config.basic_auth_username = ENV['AUTH_USER'] unless ENV['AUTH_USER'].blank?
    config.basic_auth_password = ENV['AUTH_PASSWORD'] unless ENV['AUTH_PASSWORD'].blank?
  
    config.add_custom_check do
      File.exists?("$custom_file") ? '' : '$custom_file is missing!'
    end
  
    config.add_custom_check('pass') do
      ''
    end
  
    config.on_failure do |checks, msg|
      File.open('tmp/health_check_failure.txt', 'w') do |f|
        f.puts "FAILED: #{checks}, MESSAGE: #{msg}"
      end
    end
  
    config.on_success do |checks|
      File.open('tmp/health_check_success.txt', 'w') do |f|
        f.puts "PASSED: #{checks}"
      end
    end
  
    config.include_error_in_response_body = ENV['HIDE_ERROR_RESPONSE'].to_s !~ /^[1tTyY]/
  end
end
!

echo Setting INITIAL_BUNDLE_GEMFILE=$BUNDLE_GEMFILE
INITIAL_BUNDLE_GEMFILE="$BUNDLE_GEMFILE"
echo Unsetting BUNDLE_GEMFILE '(so Gemfile for rails application will be used)'
unset BUNDLE_GEMFILE

if [ ! -s Gemfile ]
then
    echo Missing Gemfile!
    exit 2
fi
echo Adding health_check as gem to Gemfile...
echo "gem 'health_check', path: '$base_dir'" >> Gemfile

case "$RAILS_SERVER" in
webrick|'')
        echo "Using default webrick server"
        ;;
*)
        echo "Adding $RAILS_SERVER gem to Gemfile (for use as server)"
        echo "gem '$RAILS_SERVER'" >> Gemfile
        ;;
esac
TAB=$'\t'
QUOTES='"'"'"
case "$actual_rails_version" in
*' '5.0*)
  if egrep -i 'gem.*sqlite3' Gemfile ; then
     # Can't do this as a require as we may go back to testing JRuby
     echo Force sqlite to 1.3.13+ version for Rails 5.0 ...
     gem=sqlite3
     sed -i.bak -e "s/^\([ ${TAB}]*gem[ ${TAB}]*[${QUOTES}]${gem}[${QUOTES}]\)\(.*\)$/\1, '~> 1.3.13' # overriden: \2/" Gemfile
  fi
  ;;
esac
if egrep -q REQUIRED ${INITIAL_BUNDLE_GEMFILE} ; then
  sed -n "s/^[ ${TAB}]*gem[ ${TAB}]*[${QUOTES}]\([^${QUOTES}]*\)[${QUOTES}].*REQUIRED.*/\1/p" ${INITIAL_BUNDLE_GEMFILE} | while read gem
  do
    echo "Commenting out gem '$gem' line in Gemfile"
    sed -i.bak -e "s/^\([ ${TAB}]*gem[ ${TAB}]*[${QUOTES}]${gem}[${QUOTES}].*\)$/# overriden by REQUIRED below: \1/" Gemfile
  done
  echo Adding Required gems
  egrep REQUIRED ${INITIAL_BUNDLE_GEMFILE} | tee -a Gemfile
else
  echo No required gems to be added to Gemfile 
fi

echo
echo ================= $PWD/Gemfile ===================
cat Gemfile
echo
echo ==================================================
echo running smarter_bundle install
smarter_bundle install
$rehash

if egrep webpacker Gemfile && [ ! -f config/webpacker.yml ] ; then
  echo completing setup by running rails webpacker:install ...
  $rails webpacker:install
fi

echo "Using binstubs in $railsapp/bin for rails and rake commands"
rails="$railsapp/bin/rails"
rake="$railsapp/bin/rake"

echo Checking $rails is present ...
[ -f $rails -a -f $rake ] || bundle ${BUNDLER_VERSION:+_${BUNDLER_VERSION}_} exec rake rails:update:bin || echo '(ignored rake rails:update:bin exit status)'
[ -f $rails ] || bundle ${BUNDLER_VERSION:+_${BUNDLER_VERSION}_} binstubs railties || echo '(ignored bundle exit status)'
[ -f $rails ] || bundle ${BUNDLER_VERSION:+_${BUNDLER_VERSION}_} binstubs rails || echo '(ignored bundle exit status)'
if [ ! -f $rails ]; then
    echo "Test aborted (unable to create $rails)"
    exit 2
fi

echo Checking $rake is present ...
[ -f $rake ] || bundle ${BUNDLER_VERSION:+_${BUNDLER_VERSION}_} binstubs rake || echo '(ignored bundle exit status)'
if [ ! -f $rake ]; then
    echo "Test aborted (unable to create $rake)"
    exit 2
fi

$rehash
# Fix for rvm, otherwise bundle run from rails create fails
export PATH="`pwd`/bin:$PATH"
echo ================= $PWD/Gemfile.lock ===================
cat Gemfile.lock
echo ==================================================
echo

for e in test ${RAILS_ENV2:-production}
do
    if [ -f config/environments/$e.rb ]; then
      echo ======== config/environments/$e.rb ================
      sed -i.bak -e 's/config.serve_static_assets = false/config.serve_static_assets = true   # NOTE: health_check test: changed to true/'  \
        -e 's/config.active_record.migration_error = :page_load/# & # NOTE: health_check test: commented out/'  \
        config/environments/$e.rb 
      cat config/environments/$e.rb || true
      echo
    fi
done

if egrep -q 'bootsnap.setup' config/boot.rb  ; then
  echo Commenting out bootsnap from config/boot.rb
  sed -i.bak -e 's/^\(.*bootsnap.setup\)/# \1/' config/boot.rb 
  echo "============== $PWD/config/boot.rb ============="
  cat config/boot.rb
  echo ==================================================
fi
rm -rf tmp/cache/bootsnap*
echo 

echo "============== $PWD/config/environment.rb ============="
cat config/environment.rb
echo 

echo =========================================================
case $db in
    jdbcsqlite3)
      for e in test ${RAILS_ENV2:-production}
      do
            echo
            export RAILS_ENV=$e RACK_ENV=$e
            echo "Jruby requires the database to be created before the server is started: running RAILS_ENV=$e rake db:migrate"
            $rake db:migrate 
            echo
      done
      ;;
esac

echo STATIC-FILE > public/static.txt

cat > public/ajax_example.html <<'EOF'
    <html>
    <head>
      <title>Example static and dynamic calls to health_check</title>
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
      <script>
	function parse_result(result, callback) {
	    $("#html_status_"+callback).text(result.status);
	    $("#html_body_"+callback).text(result.responseText);
	    alert(callback + " callback called");
	};

	function dynamic_call(dataType, url) {
	  $.ajax({
	    dataType: dataType,
	    url: url,
	    success: function(data, textStatus, result) {
	      $("#data_success").text(data);
	      parse_result(result, "success");
	    },
	    error: function(result, textStatus) {
	      parse_result(result, "error");
	    },
	    complete: function(result, textStatus) {
	      parse_result(result, "complete");
	    }
	  });
	};
      </script>
    </head>
    <body>
      <h1>Static calls</h1>
      <ul>
	<li><a href="http://localhost:3000/health_check/site" target="_blank">Minimal health check should always work</a>
	  (<a href="http://localhost:3000/health_check/site.json" target="_blank">json</a>,
	  <a href="http://localhost:3000/health_check/site.xml" target="_blank">xml</a>,
	  <a href="http://localhost:3000/health_check/site.html" target="_blank">html</a>)
	<li><a href="http://localhost:3000/health_check/fail" target="_blank">Force health check to fail!</a>
	  (<a href="http://localhost:3000/health_check/fail.json" target="_blank">json</a>,
	  <a href="http://localhost:3000/health_check/fail.xml" target="_blank">xml</a>,
	  <a href="http://localhost:3000/health_check/fail.html" target="_blank">html</a>)
      </ul>
      <h1>Dynamic calls</h1>
      <ul>
	<li><a href="#" onclick="dynamic_call('text', 'http://localhost:3000/health_check/site');">Minimal health check should always work</a>
	  (<a href="#" onclick="dynamic_call('json', 'http://localhost:3000/health_check/site.json');">json</a>,
	  <a href="#" onclick="dynamic_call('xml', 'http://localhost:3000/health_check/site.xml');">xml</a>,
	  <a href="#" onclick="dynamic_call('text', 'http://localhost:3000/health_check/site.html');">html</a>)

	<li><a href="#" onclick="dynamic_call('text', 'http://localhost:3000/health_check/fail');">Force health check to fail!</a>
	  (<a href="#" onclick="dynamic_call('json', 'http://localhost:3000/health_check/fail.json');">json</a>,
	  <a href="#" onclick="dynamic_call('xml', 'http://localhost:3000/health_check/fail.xml');">xml</a>,
	  <a href="#" onclick="dynamic_call('text', 'http://localhost:3000/health_check/fail.html');">html</a>)
	<li>Last results sent to success:<ul>
	  <li><b>Data:</b><span id=data_success></span>
	  <li><b>result.status:</b><span id=html_status_success></span>
	  <li><b>result.responseText:</b><span id=html_body_success></span>
	</ul>
	<li>Last results sent to error:<ul>
	  <li><b>result.status:</b><span id=html_status_error></span>
	  <li><b>result.responseText:</b><span id=html_body_error></span>
	</ul>
	<li>Last results sent to complete:<ul>
	  <li><b>result.status:</b><span id=html_status_complete></span>
	  <li><b>result.responseText:</b><span id=html_body_complete></span>
	</ul>
      </ul>
    </body>
    </html>
EOF

cat > app/controllers/example_controller.rb <<'EOF'
class ExampleController < ApplicationController

  def index
    render plain: 'example page'
  end
  
  def catchall
    render plain: 'catch all route'
  end
  
end

EOF

echo =======================================

case "$MIDDLEWARE" in
[Yy]*)
  if [ -s config/application.rb ]; then
    mv -f config/application.rb config/application.rb-old
    (
      ruby -n -e 'print if not /^  *end/..9999' config/application.rb-old | tee /tmp/t$$
      if [ ! -s /tmp/t$$ ]; then
        echo "WARNING: ruby -n -e failed silently - using sed instead!! (rbx-19mode has that problem)" >&3
        sed -e '/^  *end/,$d' config/application.rb-old
      fi

      echo "    # -----------------------------------------"
      echo "    # START OF SECTION FOR TESTING HEALTH_CHECK"
      echo "    config.middleware.insert_after Rails::Rack::Logger, HealthCheck::MiddlewareHealthcheck"
      echo "    # END OF SECTION FOR TESTING HEALTH_CHECK"
      echo "    # ---------------------------------------"
      ruby -n -e 'print if /^  *end/..9999' config/application.rb-old | tee /tmp/t$$
      if [ ! -s /tmp/t$$ ]; then
        echo "WARNING: ruby -n -e failed silently - using sed instead!! (rbx-19mode has that problem)" >&3
        sed -n -e '/^  *end/,$p' config/application.rb-old
      fi
    ) 3>&1 > config/application.rb

    #echo =============== config/application.rb-old ========================
    #cat config/application.rb-old
    echo =============== $PWD/config/application.rb ========================
    cat config/application.rb
  else
    echo FAILED: NO config/application.rb file!!
    exit 2
  fi

  echo =======================================

  ;;
esac

if [ -s config/routes.rb ]; then
  mv -f config/routes.rb config/routes.rb-old
  (
    ruby -n -e 'print if not /^end/..9999' config/routes.rb-old | tee /tmp/t$$
    if [ ! -s /tmp/t$$ ]; then
      echo "WARNING: ruby -n -e failed silently - using sed instead!! (rbx-19mode has that problem)" >&3
      sed -e '/^end/,$d' config/routes.rb-old
    fi

    # rails 3.0+
    echo "  # -----------------------------------------"
    echo "  # START OF SECTION FOR TESTING HEALTH_CHECK"
    echo "  get 'example/catchall(.:format)', controller: :example, action: :catchall"
    echo "  get 'example(.:format)', controller: :example, action: :index"
    echo "  if File.exists?('$catchall_file')"
    echo "    health_check_routes"
    echo "    # CATCH ALL ROUTE"
    echo "    get '*path', controller: :example, action: :catchall"
    echo "  end"
    echo "  # END OF SECTION FOR TESTING HEALTH_CHECK"
    echo "  # ---------------------------------------"
    ruby -n -e 'print if /^end/..9999' config/routes.rb-old | tee /tmp/t$$
    if [ ! -s /tmp/t$$ ]; then
      echo "WARNING: ruby -n -e failed silently - using sed instead!! (rbx-19mode has that problem)" >&3
      sed -n -e '/^end/,$p' config/routes.rb-old
    fi
  ) 3>&1 > config/routes.rb

  #echo =============== config/routes.rb-old ========================
  #cat config/routes.rb-old
  echo =============== config/routes.rb ========================
  cat config/routes.rb
else
  echo FAILED: NO config/routes.rb file!!
  exit 2
fi
echo =======================================

echo
echo "Created $actual_rails_version app in $railsapp using adapter $db"
echo -n "Using "
ruby --version
