#!/usr/bin/ruby
#
#--
# 
# R-Bus is a native Ruby implementation of the D-Bus protocol.
# Copyright (C) 2007 Kristoffer Lundén (kristoffer.lunden@gmail.com)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA  02110-1301, USA.  A copy of the GNU General Public License is
# also available at http://www.gnu.org/copyleft/gpl.html.
#
#++
#
# <em>rbus-send</em>
# Pure ruby version of, and compatible with dbus-send
#
# Invocation:
#   rbus-send <destination object path> <message name> [options] [arguments ...]
#
# Format of arguments:
#   <arguments>  ::= <item> | <container> [ <item> | <container>...]
#   <item>       ::= <type>:<value>
#   <container>  ::= <array> | <dict> | <variant>
#   <array>      ::= array:<type>:<value>[,<value>...] 
#   <dict>       ::= dict:<type>:<type>:<key>,<value>[,<key>,<value>...]
#   <variant>    ::= variant:<type>:<value>
#   <type>       ::= string | int16 | uint16 | int32 | uint32 | int64 | uint64 | double | byte | boolean | objpath
#
# See the TUTORIAL[link:files/TUTORIAL_txt.html] for example invocations.
#
# Stuff known to be missing/not working:
#   --reply-timeout=MSEC
#


require 'optparse'
require 'rbus'
require 'yaml'

klass = RBus::Signal
destination = nil
bus = nil
print_reply = false

opts = OptionParser.new do |opts|
  opts.banner = 'rbus-send <destination object path> <message name> [options] [arguments ...]'

  opts.on('--dest=NAME',
          String,
          'Specify the name of the connection to receive the message.') {|dest|
            destination = dest
  }
  
  opts.on('--print-reply', 
          'Wait for, and print reply.') {
    print_reply = true
    klass = RBus::MethodCall
  }
  
  opts.on('--system', 'Send to the system message bus.') {
    bus = RBus.system_bus
  }
  
  opts.on('--session', 'Send to the session message bus. (default.)') {
    bus = RBus.session_bus
  }
  
  opts.on('--type=TYPE', %w{method_call signal},
          'Specify "method_call" or "signal" (defaults to "signal").') { |type|
    klass = case type
              when 'method_call' : RBus::MethodCall
              when 'signal' : RBus::Signal
            end
  }
end

opts.version = RBus::VERSION::STRING
opts.summary_width = 18
opts.summary_indent = ""

opts.parse!

if ARGV.length < 2
  puts opts.to_s
  exit
end

object_path = ARGV.shift
member,interface = ARGV.shift.reverse.split('.',2).map{|s|s.reverse}

bus = RBus.session_bus if bus.nil?
object = bus.get_object(destination, object_path)
object.interface!(interface)

if print_reply
  puts YAML.dump(object.__send__(member, *ARGV))
else
  object.__send__(member, *ARGV){}
end
