class Coverband::Reporter

def self.baseline

def self.baseline
  require 'coverage'
  Coverage.start
  yield
  @project_directory = File.expand_path(Coverband.configuration.root)
  results = Coverage.result
  results = results.reject { |key, val| !key.match(@project_directory) || Coverband.configuration.ignore.any? { |pattern| key.match(/#{pattern}/) } }
  if Coverband.configuration.verbose
    Coverband.configuration.logger.info results.inspect
  end
  config_dir = File.dirname(Coverband.configuration.baseline_file)
  Dir.mkdir config_dir unless File.exists?(config_dir)
  File.open(Coverband.configuration.baseline_file, 'w') { |f| f.write(results.to_json) }
end

def self.clear_coverage(redis = nil)

def self.clear_coverage(redis = nil)
  redis ||= Coverband.configuration.redis
  redis.smembers('coverband').each { |key| redis.del("coverband.#{key}") }
  redis.del("coverband")
end

def self.current_root

def self.current_root
  File.expand_path(Coverband.configuration.root)
end

def self.filename_from_key(key, roots)

def self.filename_from_key(key, roots)
  filename = key
  roots.each do |root|
    filename = filename.gsub(/^#{root}/, './')
  end
  # the filename for  SimpleCov is expected to be a full path.
  # roots.last should be roots << current_root}/
  # a fully expanded path of config.root
  filename = filename.gsub('./', roots.last)
  filename
end

def self.fix_file_names(report_hash, roots)

def self.fix_file_names(report_hash, roots)
  fixed_report = {} #normalize names across servers
  report_hash.each_pair do |key, values|
    filename = filename_from_key(key, roots)
    fixed_report[filename] = values
  end
  fixed_report
end

def self.get_current_scov_data(options = {})

def self.get_current_scov_data(options = {})
  additional_scov_data = options.fetch(:additional_scov_data) { [] }
  if (additional_scov_data)
    report_scov_with_additional_data(Coverband.configuration.redis, Coverband.configuration.coverage_baseline, additional_scov_data, get_roots)
  else
    get_current_scov_data_imp(Coverband.configuration.redis, get_roots)
  end
end

def self.get_current_scov_data_imp(redis, roots)

def self.get_current_scov_data_imp(redis, roots)
  scov_style_report = {}
  redis.smembers('coverband').each do |key|
    next if Coverband.configuration.ignore.any?{ |i| key.match(i) }
    line_data = line_hash(redis, key, roots)
    if line_data
      line_key = line_data.keys.first
      previous_line_hash = scov_style_report[line_key]
      if previous_line_hash
        line_data[line_key] = merge_arrays(line_data[line_key], previous_line_hash)
      end
      scov_style_report.merge!(line_data)
    end
  end
  scov_style_report = fix_file_names(scov_style_report, roots)
  scov_style_report
end

def self.get_roots

def self.get_roots
  roots = Coverband.configuration.root_paths
  roots << "#{current_root}/"
  roots
end

def self.line_hash(redis, key, roots)

{"/Users/danmayer/projects/hearno/script/tester.rb"=>[1, nil, 1, 1, nil, nil, nil]}
>> puts Coverage.result.inspect
def self.line_hash(redis, key, roots)
  filename = filename_from_key(key, roots)
  if File.exists?(filename)
    lines_hit = redis.smembers("coverband.#{key}")
    count = File.foreach(filename).inject(0) { |c, line| c + 1 }
    if filename.match(/\.erb/)
      line_array = Array.new(count, nil)
    else
      line_array = Array.new(count, 0)
    end
    line_array.each_with_index{|line,index| line_array[index] = 1 if lines_hit.include?((index + 1).to_s) }
    {filename => line_array}
  else
    Coverband.configuration.logger.info "file #{filename} not found in project"
    nil
  end
end

def self.line_members(redis, key)

def self.line_members(redis, key)
  redis.smembers("coverband.#{key}").inspect
end

def self.merge_arrays(first, second)

[0,0,1,0,1]
merge to
[nil,0,1,0,0]
[0,0,1,0,1]
def self.merge_arrays(first, second)
  merged = []
  longest = first.length > second.length ? first : second
  longest.each_with_index do |line, index|
    if first[index] || second[index]
      merged[index] = (first[index].to_i + second[index].to_i >= 1 ? 1 : 0)
    else
      merged[index] = nil
    end
  end
  merged
end

def self.merge_existing_coverage(scov_style_report, existing_coverage)

def self.merge_existing_coverage(scov_style_report, existing_coverage)
  existing_coverage.each_pair do |key, lines|
    if current_lines = scov_style_report[key]
      lines.each_with_index do |line, index|
        if line.nil? && current_lines[index].to_i == 0
          current_lines[index] = nil
        else
          current_lines[index] = current_lines[index] ? (current_lines[index].to_i + line.to_i) : nil
        end
      end
      scov_style_report[key] = current_lines
    else
      scov_style_report[key] = lines
    end
  end
  scov_style_report
end

def self.report(options = {})

def self.report(options = {})
  begin
    require 'simplecov' if Coverband.configuration.reporter=='scov'
  rescue
    Coverband.configuration.logger.error "coverband requires simplecov in order to generate a report, when configured for the scov report style."
    return
  end
  redis = Coverband.configuration.redis
  roots = get_roots
  existing_coverage = Coverband.configuration.coverage_baseline
  open_report = options.fetch(:open_report) { true }
  if Coverband.configuration.verbose
    Coverband.configuration.logger.info "fixing root: #{roots.join(', ')}"
  end
  if Coverband.configuration.reporter == 'scov'
    additional_scov_data = options.fetch(:additional_scov_data) { [] }
    if Coverband.configuration.verbose
      print additional_scov_data
    end
    report_scov(redis, existing_coverage, additional_scov_data, roots, open_report)
  else
    lines = redis.smembers('coverband').map{ |key| report_line(redis, key) }
    Coverband.configuration.logger.info lines.join("\n")
  end
end

def self.report_line(redis, key)

/Users/danmayer/projects/cover_band_server/views/layout/erb: ["0", "33", "36", "37", "38", "39", "40", "62", "63", "66", "65532", "65533"]
/Users/danmayer/projects/cover_band_server/app/rb: ["54", "55"]
/Users/danmayer/projects/cover_band_server/views/index/erb: ["0", "2", "3", "6", "65532", "65533"]
def self.report_line(redis, key)
  "#{key}: #{line_members(redis, key)}"
end

def self.report_scov(redis, existing_coverage, additional_scov_data, roots, open_report)

def self.report_scov(redis, existing_coverage, additional_scov_data, roots, open_report)
  scov_style_report = report_scov_with_additional_data(redis, existing_coverage, additional_scov_data, roots)
  if Coverband.configuration.verbose
    Coverband.configuration.logger.info "report: "
    Coverband.configuration.logger.info scov_style_report.inspect
  end
  # add in files never hit in coverband
  SimpleCov.track_files "#{current_root}/{app,lib,config}/**/*.{rb,haml,erb,slim}"
  SimpleCov::Result.new(SimpleCov.add_not_loaded_files(scov_style_report)).format!
  if open_report
    `open #{SimpleCov.coverage_dir}/index.html`
  else
    Coverband.configuration.logger.info "report is ready and viewable: open #{SimpleCov.coverage_dir}/index.html"
  end
  S3ReportWriter.new(Coverband.configuration.s3_bucket).persist! if Coverband.configuration.s3_bucket
end

def self.report_scov_with_additional_data(redis, existing_coverage, additional_scov_data, roots)

def self.report_scov_with_additional_data(redis, existing_coverage, additional_scov_data, roots)
  scov_style_report = get_current_scov_data_imp redis, roots
  existing_coverage = fix_file_names(existing_coverage, roots)
  scov_style_report = merge_existing_coverage(scov_style_report, existing_coverage)
  additional_scov_data.each do |data|
    scov_style_report = merge_existing_coverage(scov_style_report, data)
  end
  scov_style_report
end