rspec_base = File.expand_path(File.dirname(__FILE__) + '/../../rspec/lib')
$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
require 'spec/rake/spectask'
require 'spec/translator'

$TASK_ENV_NAMES = []

def prepare_for_test env_name
  ActiveRecord::Base.establish_connection(:development)
  db_specs = ActiveRecord::Base.configurations[env_name.to_s]
  ActiveRecord::Base.connection.recreate_database(db_specs['database'])
  ActiveRecord::Base.establish_connection(env_name)
  ActiveRecord::Schema.verbose = true
  `rake db:schema:load`
end

def spec_task_name for_env
  "#{for_env}:parallel_spec"
end

{:models_test => :models, :controllers_test => :controllers, 
  :lib_test => [:extensions, :initializers, :rspec_extensions, :lib, :views, :helpers]}.each do |env, spec_dirs|
  $TASK_ENV_NAMES << env
  Spec::Rake::SpecTask.new(spec_task_name(env)) do |t|
    t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
    spec_paths = Array(spec_dirs).map { |spec_dir_name| "spec/#{spec_dir_name}/**/*_spec.rb" }
    t.spec_files = FileList[*spec_paths]
    t.fail_on_error = true
  end
end

namespace :spec do
  task :fast => ["db:migrate", "db:schema:dump"] do
    env_dir = File.join(RAILS_ROOT, 'config', 'environments')

    terminated_children = 0
    process_success_vals = []

    $TASK_ENV_NAMES.each do |env_name|
      FileUtils.ln_s(File.join(env_dir, "test.rb"), File.join(env_dir, "#{env_name}.rb"), :force => true)
      fork do
        begin
          RAILS_ENV = ENV['RAILS_ENV'] = env_name.to_s
          prepare_for_test env_name
          Rake::Task[spec_task_name(env_name)].invoke
        ensure
          FileUtils.rm_rf(File.join(env_dir, "#{env_name}.rb"))
        end
      end
    end

    loop do
      Process.wait
      terminated_children += 1
      $?.success? || exit(-1)
      (terminated_children == $TASK_ENV_NAMES.length) && exit(0)
    end
  end
end