class KPM::Formatter

def compute_border(labels)

def compute_border(labels)
  border = '_'
  border = (0...labels.size).inject(border) { |res, _i| "#{res}_" }
  labels.inject(border) do |res, lbl|
    (0...lbl[:size] + 2).each { |_s| res = "#{res}_" }
    res
  end
end

def compute_format(labels)

def compute_format(labels)
  format = '|'
  labels.inject(format) { |res, lbl| "#{res} %#{lbl[:size]}s |" }
end

def compute_labels(data, labels)

Return labels for each row and update the labels hash with the size of each column
def compute_labels(data, labels)
  seen_labels = Set.new
  labels_format_argument = []
  data.each_key do |key|
    v = data[key]
    labels.each do |e|
      # sanitize entry at the same time
      v[e[:label]] = v[e[:label]] || '???'
      # Always recompute the size
      formatter = e[:formatter].nil? ? DefaultFormatter.new(e[:label], v[e[:label]]) : e[:formatter].to_class.new(e[:label], v[e[:label]])
      prev_size = e.key?(:size) ? e[:size] : formatter.label.size
      cur_size = formatter.size
      e[:size] = prev_size < cur_size ? cur_size : prev_size
      # Labels should be unique though
      labels_format_argument << formatter.label unless seen_labels.include?(e[:label])
      seen_labels << e[:label]
    end
  end
  labels_format_argument
end

def format(data, labels = nil)

def format(data, labels = nil)
  puts format_only(data, labels)
end

def format_only(data, labels = nil)

def format_only(data, labels = nil)
  return if data.nil? || data.empty?
  if labels.nil?
    # What we want to output
    labels = [{ label: :plugin_name },
              { label: :plugin_key },
              { label: :type },
              { label: :group_id },
              { label: :artifact_id },
              { label: :packaging },
              { label: :versions, formatter: VersionFormatter.name }]
  end
  # Compute label to print along with max size for each label
  labels_format_argument = compute_labels(data, labels)
  border = compute_border(labels)
  format_string = compute_format(labels)
  formatted = "\n#{border}\n"
  formatted += Kernel.format("#{format_string}\n", *labels_format_argument)
  formatted += "#{border}\n"
  data.each_key do |key|
    v = data[key]
    arguments = []
    labels.inject(arguments) do |res, e|
      formatter = e[:formatter].nil? ? DefaultFormatter.new(e[:label], v[e[:label]]) : e[:formatter].to_class.new(e[:label], v[e[:label]])
      res << formatter.to_s
    end
    formatted += Kernel.format("#{format_string}\n", *arguments)
  end
  formatted += "#{border}\n\n"
  formatted
end