namespace :audit do

  desc "Print out the named and anonymous routes"
  task :routes => :merb_env do
    seen = []
    unless Merb::Router.named_routes.empty?
      puts "Named Routes"
      Merb::Router.named_routes.sort_by {|k,v| k}.each do |name,route|
        puts "  #{name}: #{route}"
        seen << route
      end
    end
    puts "Anonymous Routes"
    (Merb::Router.routes - seen).each do |route|
      puts "  #{route}"
    end
    nil
  end

  desc "Print out all controllers"
  task :controllers => :merb_env do
    puts "\nControllers:\n\n"
    abstract_controller_classes.each do |klass|
      if klass.respond_to?(:subclasses_list)
        puts "#{klass} < #{klass.superclass}"
        subklasses = klass.subclasses_list.sort.map { |x| Object.full_const_get(x) }
        unless subklasses.empty?
          subklasses.each { |subklass| puts "- #{subklass}" }
        else
          puts "~ no subclasses"
        end
        puts
      end
    end
  end
  
  desc "Print out controllers and their actions (use CONTROLLER=Foo,Bar to be selective)"
  task :actions => :merb_env do
    puts "\nControllers and their actions:\n\n"
    filter_controllers = ENV['CONTROLLER'] ? ENV['CONTROLLER'].split(',') : nil
    abstract_controllers = abstract_controller_classes
    classes = Merb::AbstractController.subclasses_list.sort.map { |x| Object.full_const_get(x) }
    classes = classes.select { |k| k.name.in?(filter_controllers) } if filter_controllers
    classes.each do |subklass|
      next if subklass.in?(abstract_controllers) || !subklass.respond_to?(:callable_actions)
      puts "#{subklass} < #{subklass.superclass}"
      unless subklass.callable_actions.empty?
        subklass.callable_actions.sort.each do |action, null|
          if subklass.respond_to?(:action_argument_list)
            arguments, defaults = subklass.action_argument_list[action]
            args = arguments.map { |name, value| value ? "#{name} = #{value.inspect}" : name.to_s }.join(', ')
            puts args.empty? ? "- #{action}" : "- #{action}(#{args})"
          else
            puts "- #{action}"
          end
        end
      else
        puts "~ no callable actions"
      end
      puts
    end    
  end
  
  def abstract_controller_classes
    ObjectSpace.classes.select { |x| x.superclass == Merb::AbstractController }.sort_by { |x| x.name }
  end
  
end