module Autotest::CucumberMixin

def self.included(receiver)

def self.included(receiver)
  receiver::ALL_HOOKS << [:run_features, :ran_features]
end

def all_features_good

def all_features_good
  features_to_run == ""
end

def get_to_green

def get_to_green
  begin
    super
    run_features
    wait_for_changes unless all_features_good
  end until all_features_good
end

def initialize

def initialize
  super
  reset_features
end

def make_cucumber_cmd(features_to_run, dirty_features_filename)

def make_cucumber_cmd(features_to_run, dirty_features_filename)
  return '' if features_to_run == ''
  
  profile_loader = Cucumber::Cli::ProfileLoader.new
  
  profile ||= "autotest-all" if profile_loader.has_profile?("autotest-all") && features_to_run == :all
  profile ||= "autotest"     if profile_loader.has_profile?("autotest")
  profile ||= nil
  
  if profile
    args = ["--profile", profile]
  else
    args = %w{--format} << (features_to_run == :all ? "progress" : "pretty")
  end
  # No --color option as some IDEs (Netbeans) don't output them very well (1 failed step)
  args += %w{--format rerun --out} << dirty_features_filename
  args << (features_to_run == :all ? "" : features_to_run)
  
  # Unless I do this, all the steps turn up undefined during the rerun...
  unless features_to_run == :all
    args << 'features/step_definitions' << 'features/support'
  end
  
  args = args.join(' ')
  return "#{Cucumber::RUBY_BINARY} #{Cucumber::BINARY} #{args}"
end

def rerun_all_features

def rerun_all_features
  reset_features
  run_features
end

def reset_features

def reset_features
  self.features_to_run = :all
end

def run

def run
  hook :initialize
  reset
  reset_features
  add_sigint_handler
  self.last_mtime = Time.now if $f
  loop do # ^c handler
    begin
      get_to_green
      if self.tainted then
        rerun_all_tests
        rerun_all_features if all_good
      else
        hook :all_good
      end
      wait_for_changes
      # Once tests and features are green, reset features every
      # time a file is changed to see if anything breaks.
      reset_features
    rescue Interrupt
      break if self.wants_to_quit
      reset
      reset_features
    end
  end
  hook :quit
end

def run_features

def run_features
  hook :run_features
  Tempfile.open('autotest-cucumber') do |dirty_features_file|
    cmd = self.make_cucumber_cmd(self.features_to_run, dirty_features_file.path)
    return if cmd.empty?
    puts cmd unless $q
    old_sync = $stdout.sync
    $stdout.sync = true
    self.results = []
    line = []
    begin
      open("| #{cmd}", "r") do |f|
        until f.eof? do
          c = f.getc or break
          if RUBY_VERSION >= "1.9" then
            print c
          else
            putc c
          end
          line << c
          if c == ?\n then
            self.results << if RUBY_VERSION >= "1.9" then
                              line.join
                            else
                              line.pack "c*"
                            end
            line.clear
          end
        end
      end
    ensure
      $stdout.sync = old_sync
    end
    self.features_to_run = dirty_features_file.read.strip
    self.tainted = true unless self.features_to_run == ''
  end
  hook :ran_features
end