#
# Rakefile managing Selenium Grid components
#
require "net/http"
require "yaml"
require File.dirname(__FILE__) + '/lib/ruby/tcp_socket_extensions'
require File.dirname(__FILE__) + '/lib/ruby/file_extensions'
require File.dirname(__FILE__) + '/lib/ruby/java/classpath'
require File.dirname(__FILE__) + '/lib/ruby/java/vm'

desc "Print help"
task :help do
  puts <<-EOS
  
 Rake tasks to manage a Selenium Grid on a *single* machine.

   NOTE: To manage a Grid accross *multiple* machines use the 
         Capistrano recipes provided with Selenium Grid distribution
 
 
 Start the Hub and 15 Remote Controls
 ------------------------------------
 
    rake all:start
   
 Stop the Hub and 15 Remote Controls
 -----------------------------------
 
    rake all:stop
   
 Restart the Hub and 15 Remote Controls
 --------------------------------------

    rake all:restart

 Start the Hub with only 10 Remote Controls, ports 5000 to 5010
 --------------------------------------------------------------

    rake all:restart PORTS=5000-5010

  Stop them with

    rake all:stop PORTS=5000-5010
  
 Start 5 Remote Controls with the Hub, ports 6500 to 6505
 --------------------------------------------------------

   rake rc:start_all PORTS=6500-6505

 Start a single Remote Control on port 6666
-------------------------------------------

    rake rc:start PORT=6666

   
  EOS
end

desc "Restart all  services (Hub a Remote Controls"
task :'all:restart' do
  Rake::Task[:'all:stop'].execute("dummy") rescue nil
  Rake::Task[:'all:start'].execute "dummy"
end

desc "Launch all  services (Hub a Remote Controls"
task :'all:start' do
  ENV['BACKGROUND'] = "true"
  Rake::Task[:'hub:start'].execute "dummy"
  puts "Waiting for Hub to come up..."
  TCPSocket.wait_for_service :host => "localhost", :port => hub_port
  Rake::Task[:'rc:start_all'].execute "dummy"
end

desc "Stop all  services (Hub a Remote Controls"
task :'all:stop' do
  puts "Stopping all Selenium Grid servers..."
  Rake::Task[:'rc:stop_all'].execute "dummy"
  Rake::Task[:'hub:stop'].execute "dummy" rescue nil
end

desc "Launch Hub"
task :'hub:start' do
  classpath = Java::Classpath.new(File.dirname(__FILE__))
  classpath = classpath << "." << "lib/selenium-grid-hub-standalone-*.jar"
  puts classpath.inspect
  Java::VM.new.run "com.thoughtworks.selenium.grid.hub.HubServer",
                    :classpath => classpath.definition,
                    :background => ("true" == ENV['BACKGROUND']),
                    :log_file => File.native_path(File.dirname(__FILE__) + "/log/hub.log")
end

desc "Stop Hub"
task :'hub:stop' do
  puts "Shutting down Selenium Grid hub..."
  http = Net::HTTP.new("localhost", hub_port)
  http.post('/lifecycle-manager', "action=shutdown")
end

desc "Launch Remote Control"
task :'rc:start' do
  launch_rc(:port => (ENV['PORT'] || 5555)) 
end

desc "Stop Remote Control"
task :'rc:stop' do
  http = Net::HTTP.new("localhost", ENV['PORT'] || 5555)
  puts http.post('/selenium-server/driver/', "cmd=shutDown")
end

desc "Launch Remote Control"
task :'rc:start_all' do
  ports = ENV['PORTS'] || "5000-5015"
  port_range = Range.new(*ports.split("-"))
  port_range.each do |port|
    ENV['BACKGROUND'] = "true"
    launch_rc(:port => port)
  end
end

desc"Stop Remote Controls. Usage rake rc:stop PORTS=5555-5560"
task :'rc:stop_all' do
  ports = ENV['PORTS'] || "5000-5015"
  port_range = Range.new(*ports.split("-"))
  port_range.each do |port|
    begin
      puts "Stopping Remote Control on port #{port}"
      http = Net::HTTP.new("localhost", port)
      http.post('/selenium-server/driver/', "cmd=shutDown")
    rescue Exception => e
      STDERR.puts "Could not properly shutdown remote control #{port} : #{e}"
    end
  end
end

desc "Launch a Xvnc server"
task :'xvnc:start' do
  sh "Xvnc :1 -alwaysshared -geometry 1280x1024 -depth 24 -desktop 'Selenium Grid' 2>&1 >#{File.join(File.dirname(__FILE__), "log", "X.log")} &"
end

desc "Fully Automated Demo (for continuous integration)"
task :'ci:demo' do
  begin
    Rake::Task["all:restart"].execute "dummy"
#    sh "ant run-demo-in-parallel"
    sh "ant run-demo-in-sequence"
  ensure
    Rake::Task["all:stop"].execute "dummy"
  end
end

desc "Fully Automated Ruby Example (for continuous integration)"
task :'ci:ruby-example' do
  begin
    Rake::Task["all:restart"].execute "dummy"
#    sh "(cd  examples/ruby; rake tests:run_in_parallel)"
    sh "(cd  examples/ruby; rake tests:run_in_sequence)"
  ensure
    Rake::Task["all:stop"].execute "dummy"
  end
end

def launch_rc(options)
    # Selenium Server must be first in classpath
    classpath = Java::Classpath.new(File.dirname(__FILE__))
    classpath =  classpath << "." << "vendor/selenium-server-*.jar" << "lib/selenium-grid-remote-control-standalone-*.jar"

    Java::VM.new.run "com.thoughtworks.selenium.grid.remotecontrol.SelfRegisteringRemoteControlLauncher",
                     :classpath => classpath.definition,
                     :args => rc_args(options),
                     :background => ENV['BACKGROUND'],
                     :log_file => File.join(File.dirname(__FILE__), "log", "rc-#{options[:port]}.log")
                     
end

def rc_args(options)
  args = []
  args << "-host" << (options[:host] || ENV['HOST'] || "localhost")
  args << "-port" << options[:port]
  args << "-hubUrl" << (options[:hub_url] || ENV['HUB_URL'] || "http://localhost:#{hub_port}")
  args << "-env '#{options[:environment] || ENV['ENVIRONMENT'] || "*firefox"}'" 
  args << (options[:selenium_args] || ENV['SELENIUM_ARGS'] || "")
  args
end

def hub_port
  (ENV["HUB_PORT"] || config["hub"]["port"]).to_i
end

def config
  @config ||= YAML.load(File.read(File.dirname(__FILE__) + "/grid_configuration.yml"))
end
