class Toys::Utils::HelpText::UsageStringAssembler

# @private

def add_flag(flag)

def add_flag(flag)
  flags = flag.short_flag_syntax + flag.long_flag_syntax
  last_index = flags.size - 1
  flags_str = flags.each_with_index.map do |fs, i|
    i == last_index ? fs.canonical_str : fs.str_without_value
  end.join(", ")
  flags_str = "    #{flags_str}" if flag.short_flag_syntax.empty?
  add_right_column_desc(flags_str, wrap_desc(flag.desc))
end

def add_flag_group_sections

def add_flag_group_sections
  @tool.flag_groups.each do |group|
    next if group.empty?
    @lines << ""
    desc_str = group.desc.to_s
    desc_str = "Flags" if desc_str.empty?
    @lines << desc_str + ":"
    group.flags.each do |flag|
      add_flag(flag)
    end
  end
end

def add_positional_arguments_section

def add_positional_arguments_section
  args_to_display = @tool.positional_args
  return if args_to_display.empty?
  @lines << ""
  @lines << "Positional arguments:"
  args_to_display.each do |arg_info|
    add_right_column_desc(arg_name(arg_info), wrap_desc(arg_info.desc))
  end
end

def add_right_column_desc(initial, desc)

def add_right_column_desc(initial, desc)
  initial = indent_str(initial.ljust(@left_column_width))
  remaining_doc = desc
  if initial.size <= @indent + @left_column_width
    @lines << "#{initial} #{desc.first}"
    remaining_doc = desc[1..-1] || []
  else
    @lines << initial
  end
  remaining_doc.each do |d|
    @lines << "#{' ' * (@indent + @left_column_width)} #{d}"
  end
end

def add_subtool_list_section

def add_subtool_list_section
  return if @subtools.empty?
  name_len = @tool.full_name.length
  @lines << ""
  @lines << "Tools:"
  @subtools.each do |subtool|
    tool_name = subtool.full_name.slice(name_len..-1).join(" ")
    add_right_column_desc(tool_name, wrap_desc(subtool.desc))
  end
end

def add_synopsis_section

def add_synopsis_section
  synopses = []
  synopses << namespace_synopsis unless @subtools.empty?
  synopses << (@delegate_target ? delegate_synopsis : tool_synopsis)
  first = true
  synopses.each do |synopsis|
    @lines << (first ? "Usage:  #{synopsis}" : "        #{synopsis}")
    first = false
  end
end

def arg_name(arg_info)

def arg_name(arg_info)
  case arg_info.type
  when :required
    arg_info.display_name
  when :optional
    "[#{arg_info.display_name}]"
  when :remaining
    "[#{arg_info.display_name}...]"
  end
end

def assemble

def assemble
  add_synopsis_section
  add_flag_group_sections
  add_positional_arguments_section if @tool.runnable?
  add_subtool_list_section
  @result = @lines.join("\n") + "\n"
end

def delegate_synopsis

def delegate_synopsis
  target = @delegate_target.join(" ")
  "#{@executable_name} #{@tool.display_name} [ARGUMENTS FOR \"#{target}\"...]"
end

def indent_str(str)

def indent_str(str)
  "#{' ' * @indent}#{str}"
end

def initialize(tool, executable_name, delegate_target, subtools,

def initialize(tool, executable_name, delegate_target, subtools,
               indent, left_column_width, wrap_width)
  @tool = tool
  @executable_name = executable_name
  @delegate_target = delegate_target
  @subtools = subtools
  @indent = indent
  @left_column_width = left_column_width
  @wrap_width = wrap_width
  @right_column_wrap_width = wrap_width ? wrap_width - left_column_width - indent - 1 : nil
  @lines = []
  assemble
end

def namespace_synopsis

def namespace_synopsis
  "#{@executable_name} #{@tool.display_name} TOOL [ARGUMENTS...]"
end

def tool_synopsis

def tool_synopsis
  synopsis = [@executable_name] + @tool.full_name
  synopsis << "[FLAGS...]" unless @tool.flags.empty?
  @tool.positional_args.each do |arg_info|
    synopsis << arg_name(arg_info)
  end
  synopsis.join(" ")
end

def wrap_desc(desc)

def wrap_desc(desc)
  WrappableString.wrap_lines(desc, @right_column_wrap_width)
end