


Buildwise::App.controllers :parallel do
  


  post "/builds/:id/report_test_result" do
    start_time = Time.now    
    logger.debug("Receive test report for build #{params[:id]} from #{params[:ip_address]}")
    build_id = params[:id]
    test_result_data_hash = params
    begin
      ret = handle_test_results(build_id, test_result_data_hash)
    rescue => e
      logger.warn("[ERROR] something wrong with handle test results: #{e}, #{e.backtrace}")
      ret = "ERROR!"
    end
    




    logger.info("[#{params[:ip_address]}] Processing build result #{params[:id]} result: #{Time.now - start_time} => |#{ret}|")
    if ret != "OK"
      logger.warn("[ERROR] failed to process test results: |#{ret}|!")
    end
    
    @build = Build.find_by_id(params[:id])
    if @build.nil?
      logger.warn("[ERROR] The build #{params[:id]} not found,|ERROR!|")
      return "ERROR!"
    end
    
    @project = @build.project
    if @project && @project.config.is_load_testing 
      exceeds_load_testing_time_limit?(@build) 
    end
         
    return ret
  end




  post "/builds/:id/report_load_test_result" do
    start_time = Time.now    
    logger.debug("Receive test report for build #{params[:id]} from #{params[:agent_name]}")
    build_id = params[:id]
    load_test_result_data_hash = params
    begin
      ret = handle_load_test_results(build_id, load_test_result_data_hash)
    rescue => e
      logger.warn("[ERROR] something wrong with handle load test results: #{e}")

      ret = "ERROR!"
    end
    




    logger.info("[#{params[:agent_name]}] Processing load result #{params[:id]} result: #{Time.now - start_time} => #{ret}")
    if ret != "OK"
      logger.warn("[ERROR] failed to process load test results: |#{ret}|!")
    end
    
    @build = Build.find_by_id(params[:id])
    return ret
  end
  
  
  







  get "/building", :cache => true do


    expires 5
    cache_key { request.path_info + '?' + params.slice('ip_address').to_param }

    agent_ip_address = params[:ip_address]

    @build = current_active_distrbuted_build    
    if @build
      @project = @build.project
      result = {}
      env_vars = {}

      if allow_agent_for_the_build(agent_ip_address, @build)        
        result[:build_id] = @build.id
        result[:app_name] = @project.config.app_name
        result[:agent_work_dir] = @project.config.agent_work_dir
        result[:ui_tests_dir] = @project.config.ui_tests_dir
        result[:agents_count] = @build.build_agents.count        
        result[:mode] = @project.config.is_load_testing ? "load_testing" : "functional_testing"
        result[:load_repeat_times_within_test] = @project.config.load_repeat_times_within_test 
        
        begin 
          the_ui_test_step = @project.config.build_steps.select{|x| x.name == "UI Test"}.first
          the_ui_test_step_test_syntax_framework = the_ui_test_step.get_attribute("test_syntax_framework")
          result[:test_syntax_framework] = the_ui_test_step_test_syntax_framework
        rescue => e
          result[:test_syntax_framework] = "RSpec"
        end        
        
        if @build.is_load_testing        
          result[:load_server_url] = @build.load_server_url
        end
        return result.to_json
      else        
        logger.info("Agent #{agent_ip_address} not allowed for this build")
        return {"error": "Not Allowed for build #{@build.id}"}.to_json
      end
    
    else
      return {"error": "Idle"}.to_json
    end
  end





  get "/builds/:id/next_test" do

    

    return "" if !params[:id]
    @build = Build.find_by_id(params[:id])

    if @build.nil? || @build.status != "building" then
      return "Invalid|nil"
    end

    agent_build_id = params[:id]
    if @build.id.to_s != agent_build_id
      return "Invalid|#{@build.id}"
    end

    agent_ip_address = params[:ip_address]
    @project = @build.project
    if @project && @project.config.is_load_testing       
      return "Invalid|#{@build.id}" if exceeds_load_testing_time_limit?(@build)
    end
    



    if settings.troubled_agents && settings.troubled_agents.any?
      logger.info("[#{agent_ip_address}] Request a test to run ..., Troubled agents => #{settings.troubled_agents}")
    else
      logger.info("[#{agent_ip_address}] Request a test to run.")
    end

    start_assign_time = Time.now
    if settings.troubled_agents.keys.include?(agent_ip_address) then
      if Time.now > settings.troubled_agents[agent_ip_address][:expired_at]
        settings.troubled_agents.delete(agent_ip_address)
      elsif settings.troubled_agents[agent_ip_address][:reset_sent]
        settings.troubled_agents[agent_ip_address][:reset_sent] = true
        return "reset"
      else
        return "Invalid|#{@build.id}"
      end
      logger.info("Troubled agent #{agent_ip_address}; alert reset")
    end

    begin
      settings.semaphore.lock if settings.semaphore
      spec_file = @build.next_grid_test(agent_ip_address)
    rescue => e
      logger.error("[#{agent_ip_address}] Failed to get next test, #{e}")      
    ensure
      settings.semaphore.unlock if settings.semaphore
    end
    







    
    logger.info("[#{agent_ip_address}] Assigned test : #{spec_file.filename}, took #{Time.now - start_assign_time} seconds") if spec_file
    return spec_file.nil? ? "" : spec_file.filename + "|#{spec_file.id}"
  end


end