#!/usr/bin/ruby

#--
# Copyright 2009-2010 by Stefan Rusterholz.
# All rights reserved.
# See LICENSE.txt for permissions.
#++



Version = "0.4.0" # Executable version

# assume baretest is not installed and this is a cold-run from source
lib_dir = File.expand_path("#{__FILE__}/../../lib")
$LOAD_PATH.unshift(lib_dir) if File.directory?(lib_dir)
lib_dir = File.expand_path("#{__FILE__}/../../../command/lib")
$LOAD_PATH.unshift(lib_dir) if File.directory?(lib_dir)



require 'command'
require 'baretest'



# Specify commands and options
Command "run" do
  # global arguments
  virtual_argument :command, '[command]', "The command to run. See `baretest commands`"
  virtual_argument :options, '[options]', "The flags and options, see in the \"Options\" section."

  # global options
  o :commands,    nil,  '--commands', :Boolean, "overview over the commands"
  o :help,        '-h', '--help',     :Boolean, "help for usage and flags"
  o :version,     '-v', '--version',  :Boolean, "print the version and exit"
  o :init,        nil,  '--init',     "Deprecated form for `baretest --init`"

  # specify the 'run' command, its default options, its options and helptext
  command "run", :format => 'cli', :interactive => false, :verbose => false do
    usage

    virtual_argument :command
    virtual_argument :options
    virtual_argument :selector, '*(selector | -selector)', :String,
      "The tests to run. Example:\n" \
      "  baretest -- test/suite/a -test/suite/a/x @tag -@other %failure -%pending\n" \
      "Defaults to 'test/{suite,unit,integration,system}\n" \
      "See `baretest selectors` to get more information"

    text "\nDefault command is 'run', which runs the testsuite or the provided testfiles.\n\nOptions:\n"

    o :commands
    o :debug,       '-d', '--debug',         :Boolean, "set debugging flags (set $DEBUG to true)"
    o :interactive, '-i', '--interactive',   :Boolean, "drop into IRB on error or failure. Use 'help!' in the irb session for more information"
    o :format,      '-f', '--format FORMAT', :String,  "use FORMAT for output, see `baretest formats`"
    o :setup_file,  '-s', '--setup FILE',    :File,    "specify setup file"
    o :verbose,     '-w', '--warn',          :Boolean, "turn warnings on for your script"
    o :help
    o :version
    o :init

    text ""

    placeholder :format_options

    text "\nEnvironment variables:\n"

    env_option :format,      'FORMAT'
    env_option :verbose,     'VERBOSE'
    env_option :interactive, 'INTERACTIVE'
  end

  command "init" do
    usage

    virtual_argument :command
    virtual_argument :options
    text "\n  Create the necessary directories and files"

    o :help
  end

  command "reset" do
    usage

    virtual_argument :command
  end

  command "formats" do
    usage

    virtual_argument :command
  end

  command "env" do
    usage

    virtual_argument :command
  end

  command "version" do
    usage

    virtual_argument :command
  end

  command "commands" do
    usage

    virtual_argument :command
  end

  command "selectors" do
    usage

    virtual_argument :command
  end

  command "help" do
    usage

    virtual_argument :command
  end
end



# Execute command
Command.with(ARGV) do
  # parse out the command
  command = command!
  # parse all options we know about and leave alone those we don't
  options = options! :ignore_invalid_options

  # some options are equivalent to commands - if they are set, change the
  # command
  if set = [:help, :commands, :version].find { |flag| options[flag] } then
    run_command = set.to_s
  elsif options[:init]
    abort "`#{$0} --init` is depreciated, please use `baretest init`."
  else
    run_command = command
  end
  if %w[run help].include?(command) then
    formatter = BareTest::CommandLine.load_formatter(options[:format])

    definition[command].content_for :format_options do |d|
      if formatter.is_a?(BareTest::Formatter) then
        d.default_options.update(formatter.command[:option_defaults]) do |k,v1,v2| v2 end
        formatter.command[:elements].each do |key, args|
          d.send(key, *args)
        end
      else
        d.text "Formatter '#{options[:format]}' does not specify any custom options."
      end
    end
  end

  options = options! # reparse with new information

  case run_command
    when "run" # run the testsuite/-file
      begin
        success = BareTest::CommandLine.run(arguments, options)
      rescue BareTest::InvalidSelectors => e
        puts e
        puts "Valid state selectors are: #{BareTest::ValidStateSelectors.join(', ')}"
        success = false
      end
      exit(success ? 0 : 1)
    when "init" # create the test directory
      BareTest::CommandLine.init(arguments, options)
    when "reset" # trash runtime stats & caching
      BareTest::CommandLine.reset(arguments, options)
    when "formats" # list available formats
      BareTest::CommandLine.formats(arguments, options)
    when "env" # show information about baretest (config, version, paths, ...)
      BareTest::CommandLine.env(arguments, options)
    when "version" # show version information about baretest
      BareTest::CommandLine.version(arguments, options)
    when "selectors" # show version information about selectors baretest recognizes
      BareTest::CommandLine.selectors(arguments, options)
    when "help"
      if command == 'help' then
        BareTest::CommandLine.help(arguments, options)
      else
        puts definition[command].usage_text
      end
    when "commands"
      BareTest::CommandLine.commands(arguments, options)
    else
      puts "Unknown command '#{command}'"
      BareTest::CommandLine.commands(arguments, options)
  end
end
