#! /usr/bin/env ruby

require 'optparse'
require 'rock/rock_inspect'

search_for = []
@search_filter = Hash.new
if !Rock::Inspect.has_vizkit?
    @search_filter[:no_plugins] = true
end

def disable_all
    @search_filter[:no_ports] = true
    @search_filter[:no_tasks] = true
    @search_filter[:no_deployments] = true
    @search_filter[:no_types] = true
    @search_filter[:no_widgets] = true
    @search_filter[:no_plugins] = true
    @search_filter[:no_projects] = true
end

parser = OptionParser.new do |opt|
    opt.banner = <<-EOT

usage: rock-inspect <search term>

 Searches for <search term> in installed oroGen projects,
 vizkit plugins and displays the definition of 
 the matching objects.

Examples:
 rock-inspect camera --show_deployments
 rock-inspect -t camera -T FramePair --show_tasks

    EOT

    opt.on('--help') do
        puts self
        exit 0
    end
    opt.on('-t', '--tasks TASK', 'if given, will filter out all items which are not related to TASK.') do |task|
        @search_filter[:tasks] = /#{task}/
    end
    opt.on('-T', '--types TYPES', 'if given, will filter out all items which are not related to TYPES.') do |type|
        @search_filter[:types] = /#{type}/
    end
    opt.on('-d', '--deployments DEPLOYMENTS', 'if given, will filter out all items which are not related to DEPLOYMENTS.') do |deployment|
        @search_filter[:deployments] = /#{deployment}/
    end
    opt.on('-D', '--projects PROJECTS', 'if given, will filter out all items which are not related to (deployment-)PROJECTS.') do |projects|
        @search_filter[:projects] = /#{projects}/
    end
    opt.on('-P', '--ports PORTS', 'if given, will filter out all items which are not related to PORTS.') do |port|
        @search_filter[:ports] = /#{port}/
    end

    if Rock::Inspect.has_vizkit?
        opt.on('-p', '--plugins PLUGINS', 'if given, will filter out all item which are not related to plugins)') do |plugin|
            @search_filter[:plugin_name] = /#{plugin}/
        end
    end

    opt.on('--show-types','if given, will only display types. Can be combined with other show options.') do
        disable_all unless @search_filter.has_key? :no_types
        @search_filter.delete :no_types
    end
    opt.on('--show-ports','if given, will only display ports. Can be combined with other show options.') do
        disable_all unless @search_filter.has_key? :no_ports
        @search_filter.delete :no_ports
    end
    opt.on('--show-tasks','if given, will only display tasks. Can be combined with other show options.') do
        disable_all unless @search_filter.has_key? :no_tasks
        @search_filter.delete :no_tasks
    end
    opt.on('--show-deployments','if given, will only display deployments. Can be combined with other show options.') do
        disable_all unless @search_filter.has_key? :no_deployments
        @search_filter.delete :no_deployments
    end
    opt.on('--show-projects','if given, will only display projects. Can be combined with other show options.') do
        disable_all unless @search_filter.has_key? :no_projects
        @search_filter.delete :no_projects
    end

    if Rock::Inspect.has_vizkit?
    opt.on('--show-plugins','if given, will only display widgtes. Can be combined with other show options.') do
        disable_all unless @search_filter.has_key? :no_plugins
        @search_filter.delete :no_plugins
    end
    opt.on('--show-plugins','if given, will only display plugins. Can be combined with other show options.') do
        disable_all unless @search_filter.has_key? :no_plugins
        @search_filter.delete :no_plugins
    end
    end
    opt.on('--debug') do
        debug = true
    end
    opt.on('--help') do
        puts parser
        exit(0)
    end
end

remaining = parser.parse(ARGV)
if remaining.empty? && @search_filter.empty? 
    STDERR.puts parser
    exit(1)
end

begin
    Orocos.load
    remaining = remaining.join("|")
    result = Rock::Inspect.find(remaining, @search_filter)
rescue Interrupt
    Orocos.warn "Interrupted"
    exit 1
end

views = result.map do |item|
    case item.object
    when Orocos::Spec::TaskContext
        Rock::TaskView.new(item)
    when Orocos::Spec::Port
        Rock::PortView.new(item) 
    when Orocos::Spec::Deployment
        Rock::DeploymentView.new(item) 
    when Class
        if item.object <= Typelib::Type
            Rock::TypeView.new(item) 
        else
            raise "unexpected search result object #{item} of type #{item.object}"
        end
    else
        if Rock::Inspect.has_vizkit?
            case item.object
            when Vizkit::PluginSpec
                Rock::WidgetView.new(item)
            else
                raise "unexpected search result object #{item} of type #{item.object}"
            end
        end
    end
end

result = views.compact.uniq.sort_by(&:name).each { |t| pp t }
if result.empty?
    STDERR.puts "nothing was found for pattern = #{remaining}" 
    STDERR.puts " filter deployments = #{@search_filter[:deployments]}" if @search_filter.has_key?(:deployments)
    STDERR.puts " filter tasks = #{@search_filter[:tasks]}" if @search_filter.has_key?(:tasks)
    STDERR.puts " filter ports = #{@search_filter[:ports]}" if @search_filter.has_key?(:ports)
    STDERR.puts " filter types = #{@search_filter[:types]}" if @search_filter.has_key?(:types)
    STDERR.puts " filter plugins = #{@search_filter[:plugin_name]}" if @search_filter.has_key?(:plugin_name)
    STDERR.puts " filter projects = #{@search_filter[:projects]}" if @search_filter.has_key?(:projects)
    exit 1
end

