class Cucumber::Formatter::Usage

def add_unused_stepdefs

def add_unused_stepdefs
  @runtime.unmatched_step_definitions.each do |step_definition|
    stepdef_key = StepDefKey.new(step_definition.regexp_source, step_definition.file_colon_line)
    @stepdef_to_match[stepdef_key] = []
  end
end

def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)

def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
  step_definition = step_match.step_definition
  unless step_definition.nil? # nil if it's from a scenario outline
    stepdef_key = StepDefKey.new(step_definition.regexp_source, step_definition.file_colon_line)
    @stepdef_to_match[stepdef_key] << {
      :keyword => keyword,
      :step_match => step_match,
      :status => status,
      :file_colon_line => @step.file_colon_line,
      :duration => @duration
    }
  end
  super
end

def aggregate_info

def aggregate_info
  @stepdef_to_match.each do |key, steps|
    if steps.empty?
      key.status = :skipped
      key.mean_duration = 0
    else
      key.status = worst_status(steps.map{ |step| step[:status] })
      total_duration = steps.inject(0) {|sum, step| step[:duration] + sum}
      key.mean_duration = total_duration / steps.length
    end
  end
end

def before_features(features)

def before_features(features)
  print_profile_information
end

def before_step(step)

def before_step(step)
  @step = step
  @start_time = Time.now
end

def before_step_result(*args)

def before_step_result(*args)
  @duration = Time.now - @start_time
end

def initialize(runtime, path_or_io, options)

def initialize(runtime, path_or_io, options)
  @runtime = runtime
  @io = ensure_io(path_or_io, "usage")
  @options = options
  @stepdef_to_match = Hash.new{|h,stepdef_key| h[stepdef_key] = []}
end

def max_length

def max_length
  [max_stepdef_length, max_step_length].compact.max
end

def max_step_length

def max_step_length
  @stepdef_to_match.values.to_a.flatten.map do |step|
    step[:keyword].unpack('U*').length + step[:step_match].format_args.unpack('U*').length
  end.max
end

def max_stepdef_length

def max_stepdef_length
  @stepdef_to_match.keys.flatten.map{|key| key.regexp_source.unpack('U*').length}.max
end

def print_step_definition(stepdef_key)

def print_step_definition(stepdef_key)
  @io.print format_string(sprintf("%.7f", stepdef_key.mean_duration), :skipped) + " " unless @options[:dry_run]
  @io.print format_string(stepdef_key.regexp_source, stepdef_key.status)
  if @options[:source]
    indent = max_length - stepdef_key.regexp_source.unpack('U*').length
    line_comment = "   # #{stepdef_key.file_colon_line}".indent(indent)
    @io.print(format_string(line_comment, :comment))
  end
  @io.puts
end

def print_steps(stepdef_key)

def print_steps(stepdef_key)
  @stepdef_to_match[stepdef_key].each do |step|
    @io.print "  "
    @io.print format_string(sprintf("%.7f", step[:duration]), :skipped) + " " unless @options[:dry_run]
    @io.print format_step(step[:keyword], step[:step_match], step[:status], nil)
    if @options[:source]
      indent = max_length - (step[:keyword].unpack('U*').length + step[:step_match].format_args.unpack('U*').length)
      line_comment = " # #{step[:file_colon_line]}".indent(indent)
      @io.print(format_string(line_comment, :comment))
    end
    @io.puts
  end
end

def print_summary(features)

def print_summary(features)
  add_unused_stepdefs
  aggregate_info
  if @options[:dry_run]
    keys = @stepdef_to_match.keys.sort {|a,b| a.regexp_source <=> b.regexp_source}
  else
    keys = @stepdef_to_match.keys.sort {|a,b| a.mean_duration <=> b.mean_duration}.reverse
  end
  keys.each do |stepdef_key|
    print_step_definition(stepdef_key)
    if @stepdef_to_match[stepdef_key].any?
      print_steps(stepdef_key)
    else
      @io.puts("  " + format_string("NOT MATCHED BY ANY STEPS", :failed))
    end
  end
  @io.puts
  super
end

def worst_status(statuses)

def worst_status(statuses)
  [:passed, :undefined, :pending, :skipped, :failed].find do |status|
    statuses.include?(status)
  end
end