#!/usr/bin/env ruby
require 'readline'
require 'English'
require 'slop'

ENV['RACK_ENV'] ||= 'production'

# display name for tools like `ps`
$PROGRAM_NAME = 'neurohmmerapp'

begin
  Slop.parse!(strict: true, help: true) do
    banner <<BANNER
SUMMARY:
  NeuroHmmer - Identify Neuropeptide Precursors 

USAGE:
  $ neurohmmerapp [options]

Examples:
  # Launch NeuroHmmerApp with the given config file
  $ neurohmmerapp --config ~/.neurohmmerapp.conf

  # Launch NeuroHmmerApp with 8 threads at port 8888
  $ neurohmmerapp --num_threads 8 --port 8888

  # Create a config file with the other arguments
  $ neurohmmerapp -s -d ~/database_dir

BANNER
    on 'c', 'config_file=',
       'Use the given configuration file',
       argument: true

    on 'g', 'public_dir=',
       'dhe public directory that is served to the web application.',
       argument: true

    on 'b', 'bin=',
       'Load HMMER 3.0 binaries from this directory',
       argument: true,
       as: Array

    on 'n', 'num_threads=',
       'Number of threads to use to run a BLAST search',
       argument: true

    on 'H', 'host=',
       'Host to run NeuroHmmerApp on',
       argument: true

    on 'p', 'port=',
       'Port to run NeuroHmmerApp on',
       argument: true

    on 's', 'set',
       'Set configuration value in default or given config file'

    on 'D', 'devel',
       'Start NeuroHmmerApp in development mode'

    on '-v', '--version',
       'Print version number of NeuroHmmerApp that will be loaded'

    on '-h', '--help',
       'Display this help message'

    clean_opts = lambda do |hash|
      hash.delete_if { |k, v| k == :set || v.nil? }
      hash
    end

    run do
      if version?
        require 'neurohmmerapp/version'
        puts NeuroHmmerApp::VERSION
        exit
      end

      ENV['RACK_ENV'] = 'development' if devel?

      # Exit gracefully on SIGINT.
      stty = `stty -g`.chomp
      trap('INT') do
        puts ''
        puts 'Aborted.'
        system('stty', stty)
        exit
      end

      require 'neurohmmerapp'

      begin
        NeuroHmmerApp.init clean_opts[to_h]

      # The aim of following error recovery scenarios is to guide user to a
      # working NeuroHmmerApp installation. We expect to land following
      # error scenarios either when creating a new NeuroHmmerApp (first
      # time or later), or updating config values using -s CLI option.

      rescue NeuroHmmerApp::CONFIG_FILE_ERROR => e

        puts e
        exit!

      rescue NeuroHmmerApp::BIN_DIR_NOT_FOUND => e

        puts e

        unless bin?
          puts 'You can set the correct value by running:'
          puts
          puts '  neurohmmerapp -s -b <value>'
          puts
        end

        exit!


      rescue NeuroHmmerApp::NUM_THREADS_INCORRECT => e

        puts e

        unless num_threads?
          puts 'You can set the correct value by running:'
          puts
          puts '  neurohmmerapp -s -n <value>'
          puts
        end

        exit!

      rescue => e
        # This will catch any unhandled error and some very special errors.
        # Ideally we will never hit this block. If we do, there's a bug in
        # NeuroHmmerApp or something really weird going on. If we hit this
        # error block we show the stacktrace to the user requesting them to
        # post the same to our Google Group.
        puts <<MSG
Something went wonky

Looks like you have encountered a bug in NeuroHmmerApp. Please could you
report this incident here -
https://github.com/wurmlab/neurohmmerapp/issues

Error:
#{e.backtrace.unshift(e.message).join("\n")}
MSG
        exit
      end

      if set?
        NeuroHmmerApp.config.write_config_file
        exit
      end

      NeuroHmmerApp.config.write_config_file if fetch_option(:set).value

      NeuroHmmerApp.run
    end
  end
rescue Slop::Error => e
  puts e
  puts "Run '#{$PROGRAM_NAME} -h' for help with command line options."
  exit
end