#!/usr/bin/env ruby
ENV['RAILS_ENV'] = 'test'
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require File.expand_path(File.dirname(__FILE__)) + "/../test/test_helper"

Suse::Backend.do_not_start_test_backend

perlopts="-I#{Rails.root}/../backend -I#{Rails.root}/../backend/build"

if File.exists?("#{Rails.root}/tmp/backend_config") 
  puts "Old backend data is there. checking if we can stop it"
  %w{bs_srcserver bs_repserver bs_service bs_sched bs_publish}.each do |srv|
    system("cd #{Rails.root}/tmp/backend_config && exec perl #{perlopts} ./#{srv} --stop 2>&1 && sleep 2")
  end
end

# check for still running daemons from former run
[ '3200', '3201', '3202' ].each do |port|
  begin
    Net::HTTP.start(CONFIG['source_host'], port) {|http| http.get('/') }
    puts "ERROR Port #{port} is already in use, maybe from former unclean shutdown, aborting ..."
    exit 1
  rescue Errno::ECONNREFUSED, Errno::ENETUNREACH
    # Connect failed, good :)
    next
  end
end

schedulerdone_file = Rails.root.join("tmp", "scheduler.done")
File.delete(schedulerdone_file) if File.exists?(schedulerdone_file)
Thread.abort_on_exception = true
srcsrv_out = nil
reposrv_out = nil
servicesrv_out = nil
publishsrv_out = nil
dienow = false
logger = Rails.logger
FileUtils.rm_rf("#{Rails.root}/tmp/backend_data")
FileUtils.rm_rf("#{Rails.root}/tmp/backend_config")

# minimal auth
@http_user = User.find_by_login( "king" )
unless @http_user
  # we only need the fixtures if rake test didn't load it yet
  system("rake --trace db:fixtures:load")
end
User.current = @http_user

puts "Creating backend config at #{Rails.root}/tmp/backend_config/BSConfig.pm"
FileUtils.mkdir "#{Rails.root}/tmp/backend_config"
file = File.open("#{Rails.root}/tmp/backend_config/BSConfig.pm", "w")
File.open("#{Rails.root}/../backend/BSConfig.pm.template") do |template|
  template.readlines.each do |line|
    line.gsub!(/our \$ipaccess/, 'our $ipaccess = undef; our $dummy')
    line.gsub!(/(our \$bsuser)/, '#\1')
    line.gsub!(/(our \$bsgroup)/, '#\1')
    line.gsub!(/^(my \$hostname).*/, '\1 = "localhost";')
    line.gsub!(/our \$bsdir = .*/, "our $bsdir = '#{Rails.root}/tmp/backend_data';")
    line.gsub!(/our \$servicedir = .*/, "our $servicedir = '#{Rails.root}/test/fixtures/backend/services';")
    line.gsub!(/:5352/, ":#{CONFIG['source_port']}")
    line.gsub!(/:5252/, ":3201") # repservier, used via source server
    line.gsub!(/:5152/, ":3202") # source service, used via source server
    file.print line
  end
end
file.close

%w{bs_admin bs_srcserver bs_repserver bs_service bs_sched bs_publish bs_productconvert}.each do |srv|
  FileUtils.symlink("#{Rails.root}/../backend/#{srv}", "#{Rails.root}/tmp/backend_config/#{srv}")
  unless system("cd #{Rails.root}/tmp/backend_config && exec perl -c #{perlopts} ./#{srv} 2>&1")
    puts "ERROR: syntax broken of #{srv}"
    exit 1
  end
end

puts "Starting backend srcserver..."
srcsrv = Thread.new do
  srcsrv_out = IO.popen("cd #{Rails.root}/tmp/backend_config; exec perl #{perlopts} ./bs_srcserver 2>&1")
  puts "Started backend srcserver with pid: #{srcsrv_out.pid}"
  begin
    Process.setpgid srcsrv_out.pid, 0
  rescue Errno::EACCES
    puts "Could not set backend srcserver group to root"
    # what to do?
  end
  while srcsrv_out && !dienow
    begin
      line = srcsrv_out.gets
      break if line.nil?
      logger.debug line.strip unless line.empty?
    rescue IOError
      break
    end
  end
end

puts "Starting backend repserver..."
reposrv = Thread.new do
  reposrv_out = IO.popen("cd #{Rails.root}/tmp/backend_config; exec perl #{perlopts} ./bs_repserver 2>&1")
  puts "Started backend repserver with pid #{reposrv_out.pid}"
  begin
    Process.setpgid reposrv_out.pid, 0
  rescue Errno::EACCES
    # what to do?
    puts "Could not set backend repserver group to root"
  end
  while reposrv_out && !dienow
    begin
      line = reposrv_out.gets
      break if line.nil?
      logger.debug line.strip unless line.empty?
    rescue IOError
      break
    end
  end
end

puts "Starting backend serviceserver..."
servicesrv = Thread.new do
  servicesrv_out = IO.popen("cd #{Rails.root}/tmp/backend_config; exec perl #{perlopts} ./bs_service 2>&1")
  puts "Started backend service server with pid #{servicesrv_out.pid}"
  begin
    Process.setpgid servicesrv_out.pid, 0
  rescue Errno::EACCES
    # what to do?
    puts "Could not set backend serviceserver group to root"
  end
  while servicesrv_out && !dienow
    begin
      line = servicesrv_out.gets
      break if line.nil?
      logger.debug line.strip unless line.empty?
    rescue IOError
      break
    end
  end
end

puts "Starting backend publisher..."
publishsrv = Thread.new do
  publishsrv_out = IO.popen("cd #{Rails.root}/tmp/backend_config; exec perl #{perlopts} ./bs_publish 2>&1")
  puts "Started backend publish server with pid #{publishsrv_out.pid}"
  begin
    Process.setpgid publishsrv_out.pid, 0
  rescue Errno::EACCES
    # what to do?
    puts "Could not set backend publish server group to root"
  end
  while publishsrv_out && !dienow
    begin
      line = publishsrv_out.gets
      logger.debug line.strip unless line.blank?
      sleep 0.5
    rescue IOError
      break
    end
  end
end

while !dienow
  puts "Connecting to srcserver..."
  begin
    Net::HTTP.start(CONFIG['source_host'], CONFIG['source_port']) {|http| http.get('/') }
  rescue Errno::ECONNREFUSED, Errno::ENETUNREACH
    sleep 0.5
    next
  end
  break
end

while !dienow
  puts "Connecting to repserver..."
  begin
    Net::HTTP.start(CONFIG['source_host'], 3201) {|http| http.get('/') }
  rescue Errno::ECONNREFUSED, Errno::ENETUNREACH
    sleep 0.5
    next
  end
  break
end

while !dienow
  puts "Connecting to serviceserver..."
  begin
    Net::HTTP.start(CONFIG['source_host'], 3202) {|http| http.get('/') }
  rescue Errno::ECONNREFUSED, Errno::ENETUNREACH
    sleep 0.5
    next
  end
  break
end

puts "Writing config data..."
Project.all.each do |p|
  Suse::Backend.put( "/source/#{CGI.escape(p.name)}/_meta", p.to_axml)
end
Package.all.each do |p|
  Suse::Backend.put( "/source/#{CGI.escape(p.project.name)}/#{CGI.escape(p.name)}/_meta", p.to_axml)
end
Suse::Backend.put( '/issue_trackers', IssueTracker.all.to_xml(IssueTracker::DEFAULT_RENDER_PARAMS))
Suse::Backend.put( '/source/BaseDistro/_config', "Repotype: rpm-md-legacy" )
Suse::Backend.put( '/source/BaseDistro/pack1/my_file', "just a file")
Suse::Backend.put( '/source/BaseDistro/pack2/my_file', "different content")
Suse::Backend.put( '/source/BaseDistro/pack2/my_file', "second commit")
Suse::Backend.put( '/source/BaseDistro/pack3/my_file', "just a file")
Suse::Backend.put( '/source/BaseDistro2.0/_config', "Type: spec" )
Suse::Backend.post( '/source/BaseDistro2.0/pack2?cmd=commitfilelist&vrev=2.3&version=1.0', '<directory/>') # set vrev like it get created with makeolder=1
Suse::Backend.put( '/source/BaseDistro2.0/pack2/myfile', "DummyContent of BaseDistro2.0/pack2")
Suse::Backend.put( '/source/BaseDistro2.0/pack2/package.spec',File.open("#{Rails.root}/test/fixtures/backend/binary/package.spec").read())
Suse::Backend.put( '/source/BaseDistro2.0/pack2.linked/_link', "<link package=\"pack2\" cicount='copy' />")
Suse::Backend.put( '/source/BaseDistro3/_config', "Type: spec\nRepotype: rpm-md suse" )
Suse::Backend.put( '/source/BaseDistro3/pack2/package.spec',File.open("#{Rails.root}/test/fixtures/backend/binary/package.spec").read())
Suse::Backend.put( '/source/BaseDistro:Update/pack2/_link', "<link project=\"BaseDistro\" package=\"pack2\" />")
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack2/_link', "<link project=\"BaseDistro:Update\" package=\"pack2\" />")
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack2/from_devel_project', "no content")
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack3/_link', "<link project=\"BaseDistro:Update\" package=\"pack3\" />")
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack3/from_devel_project', "no content")
# HiddenProject (access flag)
Suse::Backend.put( '/source/HiddenProject/_config', "Type: spec")
Suse::Backend.put( '/source/HiddenProject/pack/my_file', "Protected Content")
Suse::Backend.put( '/source/HiddenProject/pack/package.spec', File.open("#{Rails.root}/test/fixtures/backend/binary/package.spec").read())
Suse::Backend.put( '/source/HiddenProject/target/my_file', "Protected Content target")
# BinaryprotectedProject
Suse::Backend.put( '/source/BinaryprotectedProject/_config', "Type: spec")
Suse::Backend.put( '/source/BinaryprotectedProject/bdpack/my_file', "Protected Content")
Suse::Backend.put( '/source/BinaryprotectedProject/bdpack/package.spec', File.open("#{Rails.root}/test/fixtures/backend/binary/package.spec").read())
# SourceaccessProject (sourceaccess flag)
Suse::Backend.put( '/source/SourceprotectedProject/_config', "Type: spec")
Suse::Backend.put( '/source/SourceprotectedProject/pack/my_file', "Protected Content")
Suse::Backend.put( '/source/SourceprotectedProject/pack/package.spec', File.open("#{Rails.root}/test/fixtures/backend/binary/package.spec").read())
Suse::Backend.put( '/source/SourceprotectedProject/target/my_file', "Protected Content target")
# Copytest
Suse::Backend.put( '/source/CopyTest/_config', "Type: spec")
Suse::Backend.put( '/source/CopyTest/test/my_file', "CopyTest content")
Suse::Backend.put( '/source/CopyTest/test/package.spec', File.open("#{Rails.root}/test/fixtures/backend/binary/package.spec").read())
# Apache, gets wipe binaries and similar calls
Suse::Backend.put( '/source/Apache/apache2/my_file', "just a file")

Suse::Backend.put( '/source/LocalProject/remotepackage/_link', "<link project=\"RemoteInstance:BaseDistro\" package=\"pack1\" />")
Suse::Backend.put( '/source/home:adrian:ProtectionTest/_config', "Type: spec")
Suse::Backend.put( '/source/home:adrian:ProtectionTest/aggregate/_aggregate', '<aggregatelist><aggregate project="SourceprotectedProject"><package>pack</package></aggregate></aggregatelist>' )
Suse::Backend.put( '/source/home:Iggy/_config', "Type: spec")
Suse::Backend.put( '/source/home:Iggy/TestPack/myfile', "DummyContent")
Suse::Backend.put( '/source/home:Iggy/TestPack/TestPack.spec', File.open("#{Rails.root}/test/fixtures/backend/source/home:Iggy/TestPack/TestPack.spec").read())
Suse::Backend.put( '/source/home:Iggy:branches:kde4/BranchPack/myfile', "DummyContent")
Suse::Backend.put( '/source/kde4/kdebase/myfile2', "DummyContent")
Suse::Backend.put( '/source/kde4/kdelibs/my_patch.diff', 'argl')

# manual placing of files
FileUtils.cp("#{Rails.root}/test/fixtures/backend/source/_pubkey", "#{Rails.root}/tmp/backend_data/projects/BaseDistro.pkg/_pubkey")

@http_user = nil
User.current = nil

scheduler_thread = nil

at_exit do
  scheduler_thread.join if scheduler_thread

  puts "kill #{srcsrv_out.pid}"
  Process.kill "TERM", -srcsrv_out.pid
  puts "kill #{reposrv_out.pid}"
  Process.kill "TERM", -reposrv_out.pid
  puts "kill #{servicesrv_out.pid}"
  Process.kill "TERM", -servicesrv_out.pid
  puts "kill #{publishsrv_out.pid}"
  Process.kill "TERM", -publishsrv_out.pid

  srcsrv_out.close
  srcsrv_out = nil
  srcsrv.join
  reposrv_out.close
  reposrv_out = nil
  reposrv.join
  servicesrv_out.close
  servicesrv_out = nil
  servicesrv.join
  publishsrv_out.close
  publishsrv_out = nil
  publishsrv.join
  FileUtils.rm_rf("#{Rails.root}/tmp/backend_data")
  FileUtils.rm_rf("#{Rails.root}/tmp/backend_config")
  File.delete(schedulerdone_file) if File.exists?(schedulerdone_file)
end

scheduler_thread = Thread.new do
  #
  # Prepare backend meta and binary data
  #
  
  # run scheduler once
  IO.popen("cd #{Rails.root}/tmp/backend_config; exec perl #{perlopts} ./bs_sched --testmode i586") do |io|
    # just for waiting until scheduler finishes
    io.each {|line| logger.debug line.strip unless line.blank? }
  end
  
  # Inject build job results
  inject_build_job( "home:Iggy", "TestPack", "10.2", "i586" )
  inject_build_job( "HiddenProject", "pack", "nada", "i586" )
  inject_build_job( "BinaryprotectedProject", "bdpack", "nada", "i586" )
  inject_build_job( "SourceprotectedProject", "pack", "repo", "i586" )
  inject_build_job( "BaseDistro3", "pack2", "BaseDistro3_repo", "i586" )
  
  # upload a binary file to repository directly
  Suse::Backend.put( '/build/home:Iggy/10.2/i586/_repository/delete_me.rpm?wipe=1', File.open("#{Rails.root}/test/fixtures/backend/binary/delete_me-1.0-1.i586.rpm").read() )
  
  # run scheduler again to handle the build result
  IO.popen("cd #{Rails.root}/tmp/backend_config; exec perl #{perlopts} ./bs_sched --testmode i586") do |io|
    # just for waiting until scheduler finishes
    io.each {|line| logger.debug line.strip unless line.blank? }
  end
  
  # copy build result 
  Suse::Backend.post( '/build/HiddenProject/nada/i586/packCopy?cmd=copy&opackage=pack', nil )
  Suse::Backend.post( '/build/BaseDistro/BaseDistro_repo/i586/pack2?cmd=copy&oproject=home:Iggy&orepository=10.2&opackage=TestPack', nil )
  
  # run scheduler again to handle the copy build event
  IO.popen("cd #{Rails.root}/tmp/backend_config; exec perl #{perlopts} ./bs_sched --testmode i586") do |io|
    # just for waiting until scheduler finishes
    io.each {|line| logger.debug line.strip unless line.blank? }
  end

  # touch the file
  File.open(schedulerdone_file, "w")
end

puts "DONE NOW"
$stdout.flush

trap("INT") { dienow = true }

while !dienow do
  sleep 1
end

