class TestFile < ActiveRecord::Base
  belongs_to :build
  has_many :test_cases, :dependent => :destroy

  before_create :normalize_name

  attr_reader :lines

  def before_destroy
    super
    test_cases.each do |tc|
      tc.destroy
    end
  end

  def failed?
    begin
      num_failures > 0 || num_errors > 0
    rescue => e
      return false
    end
  end

  def error_count
    if failed?
      num_failures + num_errors
    else
      0
    end
  end  
  
  
  def safe_duration
    if self.build && self.build.test_syntax_framework == "JUnit"
       sprintf('%.3f', self.duration)
    else
      sprintf('%.2f', self.duration)
    end    
  end

  def recalc
    self.test_cases.reload
    self.num_total = self.test_cases.count
    self.num_failures = self.test_cases.select{|x| !x.successful && !x.blank?}.count
    self.num_errors = self.num_total - self.test_cases.select{|x| x.successful }.count - self.num_failures
    

    the_tes_case_duration = 0 
    self.successful = true
    self.test_cases.each do |x|
      the_tes_case_duration += x.duration
      self.successful = false if !x.successful
    end
    self.duration = the_tes_case_duration if self.duration.nil? || self.duration < 0.01
  end
  

  def parse(filename = @filename)
    return unless @filename

    if @lines.nil?
      @lines = []
      File.open(filename) do |file|
        file.each_line { |line| @lines << line.rstrip }
      end
    end

=begin
    last_tc = nil
    @lines.each_with_index do |line, idx|
      if line =~ /^\s*(specify|it|story|scenario|test_case|use_case|test)\s+(.*)\s+do$/
        test_cases.each do |tc|
          if $2 == '"' + tc.name + '"' || $2 == "'" + tc.name + "'"
            tc.start_line = idx
            last_tc.end_line = idx - 1 if last_tc
            last_tc = tc
          end

        end
      end
    end # end do
=end
  end



  def artifact_file_path
    File.join(build.artifacts_dir, "ui-tests", filename)
  end




  def local_source_path(the_build = nil)
    ui_test_dir = nil
    the_build ||= self.build
    the_project = the_build.project
    

    if the_project.ui_test_local_working_dir
      begin
        ui_test_dir = the_project.ui_test_local_working_dir.gsub("\\", "/")
        project_file_relative_path = File.basename(filename)
        File.join(ui_test_dir, project_file_relative_path)
      rescue => e
        puts "[TestWise Integration] Error to find out local source path: #{ui_test_dir}, #{e}"
        return nil
      end
    else

      return nil
    end
  end


  def determine_priority
    the_project = self.build.project rescue nil     
    


    num_builds = 12
    if the_project
      recent_runs = TestFile.includes(:build).where("num_total > ?", 0).where(:filename => self.filename, :builds => {:project_id => the_project.id, :is_invalid => false}).order("test_files.created_at desc").limit(num_builds)
    else
      recent_runs = TestFile.where(:filename => self.filename).order("created_at desc").limit(10)      
    end
    
    if recent_runs.count < 1
      self.priority = 50 # first time, assign high priority
    else
      self.priority = 1
      recent_runs.each_with_index do |a_run, idx|
        if a_run.priority == 0 # special considerations
          self.priority = 0
          break
        else
          self.priority += (num_builds - idx) unless a_run.successful
        end
      end        

            

      retry_weight = (recent_runs.collect{|x| x.past_agents}.compact).count

      self.priority += retry_weight
    end
    
    


    last_3_build_percentages = []
    last_3_build_percentages << self.percentage_time_of_build
    if recent_runs.count >= 2
      last_3_build_percentages << recent_runs[-2].percentage_time_of_build
    end
    if recent_runs.count >= 3
      last_3_build_percentages << recent_runs[-3].percentage_time_of_build
    end
    
    last_3_build_percentages = last_3_build_percentages.compact
    average_test_file_duration_in_build = 1 * 100.0 / self.build.test_files.count 
    
    begin
      average_percentage = (last_3_build_percentages.sum / last_3_build_percentages.count)
    rescue => de
      average_percentage = average_test_file_duration_in_build;
    end





    duration_weight = ( (average_percentage / average_test_file_duration_in_build) * 4).round()
    duration_weight = 8 if duration_weight > 8
    

    self.priority +=  duration_weight
    

    most_recent_run = recent_runs[0] rescue nil 
    if most_recent_run &&  !most_recent_run.successful
      self.priority += 20    
     end  
  end

  def percentage_time_of_build
    if self.duration && self.build.duration && self.duration < self.build.duration
      return self.duration * 100 / self.build.duration
    elsif self.build.test_files.count() == 0
      return 0
    else

      return 1 * 100 / self.build.test_files.count 
    end    
  end
  
  
  def elpased_time
    if self.build.nil?
      return 0
    end
    
    if self.build.incomplete?
      (Time.now - self.assigned_at) rescue 0
    else
      (self.build.finish_time - self.assigned_at) rescue 0
    end    
  end

  def is_assigned?
    self.status == "Assigned"
  end


  def average_test_case_hook_time

    test_file_duration = self.duration
    test_case_count = test_cases.count
    total_test_case_duration = 0 
    test_cases.each do |tc|
      total_test_case_duration += tc.duration || 0
    end

    return (test_file_duration - total_test_case_duration) * 1.0 / test_case_count
  end

  private
  
  def normalize_name
    
    if self.build && self.build.project.config.builder_ui_test_framework       
      
      the_build_test_framework = self.build.project.config.builder_ui_test_framework 
      
      if the_build_test_framework == "VSTest"
      
        test_file_name = self.filename
        self.result_filename ||= self.filename
    
        prefix = "TestResult-"
        suffix = ".xml"
        if test_file_name.start_with?(prefix)
          self.filename = test_file_name[(prefix.length)..-1]
          self.filename.strip!
          test_file_name = self.filename
        end
    
        if test_file_name.end_with?(suffix)
          self.filename = test_file_name[0..-1*(suffix.length + 1)]
          self.filename.strip!
        end

      elsif the_build_test_framework == "pytest" || the_build_test_framework == "unittest"
        
        if self.filename.end_with?(".xml")
          self.filename = self.filename.gsub(".xml", ".py")
        end
        
      elsif the_build_test_framework == "JUnit"
        
        test_file_name = self.filename
        self.result_filename ||= self.filename
    
        prefix = "TestResult-"
        suffix = ".xml"
        if test_file_name.start_with?(prefix)
          self.filename = test_file_name[(prefix.length)..-1]
          self.filename.strip!
          test_file_name = self.filename
        end
        

        prefix = "TEST-"        
        if test_file_name.start_with?(prefix)
          self.filename = test_file_name[(prefix.length)..-1]
          self.filename.strip!
          test_file_name = self.filename
        end
    
        if test_file_name.end_with?(suffix)
          self.filename = test_file_name[0..-1*(suffix.length + 1)]
          self.filename.strip!
        end
        
      end      

    end

  end  
  
end