/*
 * call-seq:
 *   connect(...)
 *
 * Connect to the queue manager, then disconnect once the supplied code block completes
 *
 * Parameters:
 * * Since the number of parameters can vary dramatically, all parameters are passed by name in a hash
 * * Summary of parameters and their WebSphere MQ equivalents:
 *  WMQ::QueueManager.connect(                             # WebSphere MQ Equivalents:
 *   :q_mgr_name         => 'queue_manager name',
 *   :exception_on_error => true,                          # n/a
 *   :connect_options    => WMQ::MQCNO_FASTBATH_BINDING    # MQCNO.Options
 *
 *   :trace_level        => 0,                             # n/a
 *
 *   # Common client connection parameters
 *   :channel_name       => 'svrconn channel name',        # MQCD.ChannelName
 *   :connection_name    => 'localhost(1414)',             # MQCD.ConnectionName
 *   :transport_type     => WMQ::MQXPT_TCP,                # MQCD.TransportType
 *
 *   # Advanced client connections parameters
 *   :max_msg_length     => 65535,                         # MQCD.MaxMsgLength
 *   :security_exit      => 'Name of security exit',       # MQCD.SecurityExit
 *   :send_exit          => 'Name of send exit',           # MQCD.SendExit
 *   :receive_exit       => 'Name of receive exit',        # MQCD.ReceiveExit
 *   :security_user_data => 'Security exit User data',     # MQCD.SecurityUserData
 *   :send_user_data     => 'Send exit user data',         # MQCD.SendUserData
 *   :receive_user_data  => 'Receive exit user data',      # MQCD.ReceiveUserData
 *   :heartbeat_interval =>  1,                            # MQCD.HeartbeatInterval
 *   :remote_security_id => 'Remote Security id',          # MQCD.RemoteSecurityId
 *   :ssl_cipher_spec    => 'SSL Cipher Spec',             # MQCD.SSLCipherSpec
 *   :keep_alive_interval=> -1,                            # MQCD.KeepAliveInterval
 *   :mode_name          => 'LU6.2 Mode Name',             # MQCD.ModeName
 *   :tp_name            => 'LU6.2 Transaction pgm name',  # MQCD.TpName
 *   :user_identifier    => 'LU 6.2 Userid',               # MQCD.UserIdentifier
 *   :password           => 'LU6.2 Password',              # MQCD.Password
 *   :long_remote_user_id=> 'Long remote user identifier', # MQCD.LongRemoteUserId (Ptr, Length)
 *   :ssl_peer_name      => 'SSL Peer name',               # MQCD.SSLPeerName (Ptr, Length)
 *
 *   # SSL Options
 *   :key_repository     => '/var/mqm/qmgrs/.../key',        # MQSCO.KeyRepository
 *   :crypto_hardware    => 'GSK_ACCELERATOR_NCIPHER_NF_ON', # MQSCO.CryptoHardware
 *   )
 *
 * Optional Parameters
 * * :q_mgr_name => String
 *   * Name of the existing WebSphere MQ Queue Manager to connect to
 *
 *   * Default:
 *      - Server connections will connect to the default queue manager
 *      - Client connections will connect to whatever queue
 *        manager is found at the host and port number as specified
 *        by the connection_name
 *
 * * :exception_on_error => true or false
 *      Determines whether WMQ::WMQExceptions are thrown whenever
 *      an error occurs during a WebSphere MQ operation (connect, put, get, etc..)
 *
 *      Default: true
 *
 * * :connect_options => FixNum
 *   * One or more of the following values:
 *       WMQ::MQCNO_STANDARD_BINDING
 *       WMQ::MQCNO_FASTPATH_BINDING
 *       WMQ::MQCNO_SHARED_BINDING
 *       WMQ::MQCNO_ISOLATED_BINDING
 *       WMQ::MQCNO_ACCOUNTING_MQI_ENABLED
 *       WMQ::MQCNO_ACCOUNTING_MQI_DISABLED
 *       WMQ::MQCNO_ACCOUNTING_Q_ENABLED
 *       WMQ::MQCNO_ACCOUNTING_Q_DISABLED
 *       WMQ::MQCNO_NONE
 *
 *   * Multiple values can be or'd together. E.g.
 *       :connect_options=>WMQ::MQCNO_FASTPATH_BINDING | WMQ::MQCNO_ACCOUNTING_MQI_ENABLED
 *
 *   * Please see the WebSphere MQ MQCNO data type documentation for more details
 *      Default: WMQ::MQCNO_NONE
 *
 * * :trace_level => FixNum
 *   * Turns on low-level tracing of the WebSphere MQ API calls to stdout.
 *     * 0: No tracing
 *     * 1: MQ API tracing only (MQCONNX, MQOPEN, MQPUT, etc..)
 *     * 2: Include Ruby WMQ tracing
 *     * 3: Verbose logging (Recommended for when reporting problems in Ruby WMQ)
 *      Default: 0
 *
 * Common Client Connection Parameters (Client connections only)
 * * :connection_name => String (Mandatory for client connections)
 *   * Connection name, made up of the host name (or ip address) and the port number
 *   * E.g.
 *       'mymachine.domain.com(1414)'
 *       '192.168.0.1(1417)'
 *
 * * :channel_name => String
 *   * Name of SVRCONN channel defined on the QueueManager for Client Connections
 *   * Default Value:
 *       'SYSTEM.DEF.SVRCONN'
 *
 * * :transport_type     => WMQ::MQXPT_TCP,                # MQCD.TransportType
 *   * Valid Values:
 *       WMQ::MQXPT_LOCAL
 *       WMQ::MQXPT_LU62
 *       WMQ::MQXPT_TCP
 *       WMQ::MQXPT_NETBIOS
 *       WMQ::MQXPT_SPX
 *       WMQ::MQXPT_DECNET
 *       WMQ::MQXPT_UDP
 *
 *   * Default Value:
 *       WMQ::MQXPT_TCP
 *
 * For the Advanced Client Connection parameters, please see the WebSphere MQ documentation
 *
 * Note:
 * * If an exception is not caught in the code block, the current unit of work is
 *   automatically backed out, before disconnecting from the queue manager.
 *
 * Local Server Connection Example:
 *   require 'wmq/wmq'
 *
 *   WMQ::QueueManager.connect(:q_mgr_name=>'REID') do |qmgr|
 *     qmgr.put(:q_name=>'TEST.QUEUE', :data => 'Hello World')
 *   end
 *
 * Client Connection Example:
 *   require 'wmq/wmq_client'
 *
 *   WMQ::QueueManager.connect(
 *               :channel_name    => 'SYSTEM.DEF.SVRCONN',
 *               :transport_type  => WMQ::MQXPT_TCP,
 *               :connection_name => 'localhost(1414)' ) do |qmgr|
 *     qmgr.open_queue(:q_name=>'TEST.QUEUE', :mode=>:input) do |queue|
 *
 *       message = WMQ::Message.new
 *       if queue.get(:message => message)
 *         puts "Data Received: #{message.data}"
 *       else
 *         puts 'No message available'
 *       end
 *     end
 *   end
 */
VALUE QueueManager_singleton_connect(int argc, VALUE *argv, VALUE self)
{
    VALUE proc, parameters, queue_manager;

    /* Extract parameters and code block (Proc) */
    rb_scan_args(argc, argv, "1&", &parameters, &proc);

    queue_manager = rb_funcall(wmq_queue_manager, ID_new, 1, parameters);
    if(!NIL_P(proc))
    {
        if(Qtrue == QueueManager_connect(queue_manager))
        {
            struct QueueManager_singleton_connect_arg arg;
            arg.self = queue_manager;
            arg.proc = proc;
            rb_ensure(QueueManager_singleton_connect_body, (VALUE)&arg,
                      QueueManager_singleton_connect_ensure, queue_manager);
        }
        else
        {
            return Qfalse;
        }
    }
    return queue_manager;
}