#!/usr/bin/env ruby
#
require 'vizkit'
require 'optparse'

@search_filter = Hash.new
@show_and_exit = false
replay_into = nil
replay_connections = []
replay_configuration = nil
use_sample_time = false
transformer_config = nil
export_all = false
parser = OptionParser.new do |opt|
    opt.banner = <<-EOT

usage: rock-replay <logfile>

 Replays and displays log data genreated by the generic orogen logger 

Examples:
 rock-replay camera.0.log
 rock-replay folder
 rock-replay camera.0.log -t camera

    EOT

    opt.on('--help') do
        puts parser
        exit 0
    end
    opt.on('-t', '--tasks TASK', 'displays only tasks which match TASK.') do |task|
        @search_filter[:tasks] = /#{task}/
    end
    opt.on('-T', '--types TYPE', 'displays only ports which match TYPES.') do |type|
        @search_filter[:types] = /#{type}/
    end
    opt.on('-p', '--ports PORT', 'displays only ports which match PORT.') do |port|
        @search_filter[:ports] = /#{port}/
    end
    opt.on('-l', '--limit LIMIT', 'displays only ports those number of samplest does not exceed LIMIT.') do |limit|
        @search_filter[:limit] = limit.to_i
    end
    opt.on('-s', '--show', 'displays all replayed tasks on the consol and exits.') do
        @show_and_exit = true
    end
    opt.on('--into TASK', String, 'the task model name of a task in which we should replay into') do |task_model|
        replay_into = task_model
    end
    opt.on('--config CONF', String, 'if --into is given, apply the given configuration to the started task. CONF is FILE[:section1,section2] or DIR[:section1,section2]') do |confspec|
        path, sections = confspec.split(':')
        sections = (sections || '').split(',')
        if sections.empty?
            sections << "default"
        end
        replay_configuration = [path, sections]
    end
    opt.on('--connect OUTPUT:INPUT', String, 'if --into is given, this specifies a connection that should be made to the target task. OUTPUT is a stream name while INPUT is an input port on the task') do |conn|
        replay_connections << conn.split(':')
    end
    opt.on('--debug') do
        Vizkit.logger.level = Logger::INFO
    end
    opt.on('--use-sample-time', String, 'makes the alignment algorithm use sample timestamp time for alignment') do
        use_sample_time = true
    end
    opt.on('--transformer CONFIG', 'use this transformer configuration file instead of getting it from the transformer broadcaster. This loads a Vizkit3D view') do |path|
        transformer_config = path
    end
    opt.on('--export-all', 'exports all replayed tasks to CORBA') do
        export_all = true
    end
end

remaining = parser.parse(ARGV)
if remaining.empty? 
    remaining  = Qt::FileDialog::getOpenFileNames(nil,"Replay Log Files",File.expand_path("."),"Log Files (*.log)")
    if remaining.empty?
        puts parser
        exit(1)
    end
    #close window before doing anything else
    while $qApp.hasPendingEvents
        $qApp.processEvents
    end
end

Orocos.initialize       # load support for Typelib types
log = Orocos::Log::Replay.open(remaining,Typelib::Registry.new)
log.use_sample_time = use_sample_time
#select only ports which are not filtered out
log.track(true, @search_filter)

def replay(log)
    unless log.replay?
        if @search_filter.empty?
            Vizkit.warn "There are no samples in the log file!"
        else
            Vizkit.warn "No ports were selected for replay (ports with no samples cannot be selected)!"
        end
        exit 0
    end
    puts "Aligning streams. This can take a long time"
    Vizkit.control log, :show_marker=>true, :marker_type=>"/logger/Marker"
    Vizkit.exec
end

if transformer_config
    v3d = Vizkit.vizkit3d_widget
    v3d.load_transformer_config_from_broadcaster = false
    v3d.load_transformer_configuration(transformer_config.dup)
end

if export_all
    async_tasks = []
    log.each_task do |task|
        async_tasks << task.to_async
        async_tasks.last.to_ruby
    end
end

if @show_and_exit
    pp log
elsif replay_into
    Orocos.initialize
    Orocos.run replay_into => "replay#{Process.pid}" do
        task = Orocos.name_service.get "replay#{Process.pid}"

        if replay_configuration
            Orocos.apply_conf(task, *replay_configuration)
        end

        replay_connections.each do |from, to|
            input_task, input_port = from.split('.')
            log.send(input_task).port(input_port).connect_to(task.port(to), :type => :buffer, :size => 100)
        end

        if task.rtt_state == :PRE_OPERATIONAL
            task.configure
        end

        if task.rtt_state == :STOPPED
            task.start
        end
        Vizkit.display(task)

        replay(log)
    end
else
    replay(log)
end

