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
  scenarios_to_run == []
end

def cucumber

def cucumber
  File.exist?("script/cucumber") ? "script/cucumber" : "cucumber"
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(scenarios_to_run, dirty_scenarios_filename)

def make_cucumber_cmd(scenarios_to_run, dirty_scenarios_filename)
  return '' if scenarios_to_run == []
  
  profiles = YAML.load_file("cucumber.yml").keys rescue []
  
  profile ||= "autotest-all" if profiles.include?("autotest-all") and scenarios_to_run == :all
  profile ||= "autotest"     if profiles.include?("autotest")
  profile ||= nil
  
  if profile
    args = ["--profile", profile]
  else
    args = %w{features --format} << (scenarios_to_run == :all ? "progress" : "pretty")
  end
  args += %w{--format autotest --out} << dirty_scenarios_filename
  args = args.join(' ')
  
  if scenarios_to_run == :all
    scenario_args = nil
  else
    scenario_args = scenarios_to_run.map { |s| "-s '#{s}'" }.join(' ')
  end
  
  return "#{cucumber} #{args} #{scenario_args}"
end

def rerun_all_features

def rerun_all_features
  reset_features
  run_features
end

def reset_features

def reset_features
  self.scenarios_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_scenarios_file|
    cmd = self.make_cucumber_cmd self.scenarios_to_run, dirty_scenarios_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
          putc c
          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.scenarios_to_run = dirty_scenarios_file.readlines.map { |l| l.chomp }
    self.tainted = true unless self.scenarios_to_run == []
  end
  hook :ran_features
end