#!/usr/bin/env ruby

class PlainTextFormatter
  def consts(consts)
    puts "Constants"
    puts "========="
    unless consts.empty?
      consts.each { |const| puts "  - #{const}" }
    else
      puts "  (no constants)"
    end
    puts
  end

  def methods_header
    puts "Methods"
    puts "======="
  end

  def method_list(title, methods)
    puts "#{title}:"
    unless methods.empty?
      methods.each { |method| puts "  - #{method}" }
    else
      puts "  (no methods)"
    end
    puts
  end
end

class DokuwikiFormatter
  def consts(consts)
    puts "===== Constants ====="
    puts
    puts "^  Constant  ^  Notes  ^"
    unless consts.empty?
      consts.each do |const|
        puts "| <html><span style=\"background-color: #ffc;\"><code>#{const}</code></span></html>  |  FIXME  |"
      end
    else
      puts "|  No constants.  ||"
    end
    puts
  end

  def methods_header
    puts "===== Methods ====="
    puts
    puts "^  Method  ^  Notes  ^"
  end

  def method_list(title, methods)
    puts "^  #{title}  ^^"
    unless methods.empty?
      methods.each do |method|
        puts "| <html><span style=\"background-color: #ffc;\"><code>#{method}</code></span></html>  |  FIXME  |"
      end
    else
      puts "|  No methods.  ||"
    end
  end
end

def write_class_info(klass, formatter)
  formatter.consts(klass.constants.sort)
  formatter.methods_header
  formatter.method_list("Class methods", klass.singleton_methods(false).sort)
  formatter.method_list("Public methods", klass.public_instance_methods(false).sort)
  formatter.method_list("Protected methods", klass.protected_instance_methods(false).sort)
  formatter.method_list("Private methods", klass.private_instance_methods(false).sort)
end

require "optparse"

# Set default values of the options.
options = {}
options[:formatter_class] = PlainTextFormatter

# Define options...
option_parser = OptionParser.new do |option_parser|
  option_parser.banner = "Usage: class_info.rb [options] class"

  option_parser.separator ""
  option_parser.separator "Options:"

  option_parser.on("-d", "--dokuwiki", "print information as Dokuwiki table") do
    options[:formatter_class] = DokuwikiFormatter
  end

  option_parser.on("-h", "--help", "write this help") do
    puts option_parser
    exit
  end

  option_parser.on("-v", "--version", "write version information") do
    puts "0.3"
    exit
  end
end

# ...and parse the options.
begin
  option_parser.parse!(ARGV)
rescue OptionParser::InvalidOption, OptionParser::AmbiguousOption, OptionParser::MissingArgument => e
  abort e
end

abort "No class specified." if ARGV.length == 0
abort "Too many parameters specified." if ARGV.length > 2

begin
  klass = instance_eval(ARGV[0])
rescue NameError
  abort "Not a class: #{ARGV[0]}."
end

write_class_info(klass, options[:formatter_class].new)
