gem 'childprocess'

class BuildRunner

  def self.busy?
    active_builds = Build.where("status = ?", 'building')
    !active_builds.empty?
  end

  def self.next_build(project, options = {})

    outstanding_builds = BuildQueue.where("project_id = ? AND (status IS NULL OR status = ?)", project.id, 'pending')
    if outstanding_builds.empty?
      the_build = BuildQueue.new(:project_id => project.id, :status => "pending", :created_at => Time.now)
      the_build.category = options[:category] if options[:category]
      the_build.save
    else

      force = true # has schduled builds
      the_build = outstanding_builds.first
      outstanding_builds.each do |x|
        next if x == 0
        x.destroy
      end
    end

    return the_build

  end

  def self.force_build(project)
    the_build = Build.new(:project_id => project.id, :category => "manual", :status => "building")
    if project.config.is_load_testing        
      the_build.load_server_url = project.config.load_server_url
      the_build.load_max_agent_count = project.config.load_max_agent_count
    end
    the_build.start_time = Time.now
    the_build.save
    return the_build
  end

  def self.build_now(the_build)
    puts "[INFO] building #{the_build.id} now ..."
    start_time = Time.now
    return if the_build.nil? || the_build.project.nil?

    if the_build.class.name =~ /BuildQueue/
      the_build.status = "processed"
      the_build.save # (:changed => true, :validate => false)
    end




    project_identifier = the_build.project.identifier
    
    ruby_cmd = Platform.interpreter =~ /jruby/ ?  Platform.interpreter : "ruby"
    force = the_build.category == "scheduled" || the_build.category == "manual"

    require "childprocess"
    puts("[DEBUG] start build cmd => #{ruby_cmd} #{path_to_buildwise_builder} #{ENV['RACK_ENV']} #{the_build.id}")
    builds_log_dir = File.join(BUILDWISE_ROOT, "log", "builds")
    FileUtils.mkdir_p(builds_log_dir) unless File.exist?(builds_log_dir)
    build_command_output_file = File.join(builds_log_dir, "build_#{the_build.id.to_s.rjust(5, '0')}.log")    
    if File.exist?(build_command_output_file)
      FileUtils.rm(build_command_output_file)
    end      

    process = ChildProcess.build(ruby_cmd, path_to_buildwise_builder,
                                 ENV['RACK_ENV'] || "production", the_build.id.to_s, force.to_s)
                                 


    

    unless ChildProcess.windows?
      process.io.stderr = process.io.stdout = File.open(build_command_output_file, "a")
    end  
    process.start

    puts "[INFO] build runner process => |#{process.exited?}|#{process.exit_code}|"    


    sleep(0.25) 

    puts "[INFO] build runner process after minor wait (0.25s)  => |#{process.exited?}|#{process.exit_code}|" 



    
    the_build.pid = process.pid
    the_build.builder_output ||= "#{path_to_buildwise_builder} #{ENV['RACK_ENV']} #{the_build.id.to_s}\n"
    the_builder_output = File.read(build_command_output_file)
    if the_builder_output.size > 5000
      the_builder_output = the_builder_output.truncate(2048) + "\n...\n" + the_builder_output.last(2048)
    end
    the_build.builder_output += (the_builder_output + "\n\n")
    the_build.save
    
    if process.exit_code != 0 && process.exited? &&  the_build.builder_output.size > 10

      the_build.cancel
    end
    
    return the_build
  end

  def self.path_to_buildwise_builder
    File.expand_path(File.join(BUILDWISE_ROOT, 'bin', "buildwise-build.rb"))
  end
  
end