// $Id: Messenger_i.cpp 83415 2008-10-23 08:18:15Z johnnyw $

#include "orbsvcs/CosNotifyChannelAdminC.h"
#include "orbsvcs/CosNotifyCommC.h"
#include "orbsvcs/CosNamingC.h"
#include "orbsvcs/Notify/Notify_EventChannelFactory_i.h"

// The static initialization trick doesn't work with static builds.
// On SunOS 5.8 and MacOS X, the static initialization trick used
// in the CosNotification_Serv library does not work.  Including the
// initializer class here works around the problem.
#if defined (TAO_AS_STATIC_LIBS) || defined (sun) || defined (__APPLE__)
#include "orbsvcs/Notify/CosNotify_Initializer.h"
#endif /* sun || __APPLE__ */

#include "Messenger_i.h"
#include "StructuredEventSupplier_i.h"
#include <iostream>

Messenger_i::Messenger_i (CORBA::ORB_ptr orb)
: orb_ (CORBA::ORB::_duplicate(orb))

{
  try
  {
    CORBA::Object_var poa_obj = orb->resolve_initial_references("RootPOA");
    PortableServer::POA_var poa = PortableServer::POA::_narrow(poa_obj.in());

    CORBA::Object_var naming_obj =
      orb_->resolve_initial_references ("NameService");

    if (CORBA::is_nil(naming_obj.in())) {
      std::cerr << "Unable to find naming service" << std::endl;
    }

    CosNaming::NamingContext_var naming_context =
      CosNaming::NamingContext::_narrow(naming_obj.in());


    //
    //  Create an instance of TAO's notification event channel
    //

    CosNotifyChannelAdmin::EventChannelFactory_var notify_factory =
      TAO_Notify_EventChannelFactory_i::create(poa.in());

    if (CORBA::is_nil (notify_factory.in ())) {
      std::cerr << "Unable to create the notify event channel" << std::endl;
      return;
    }

    CosNotifyChannelAdmin::ChannelID id;
    CosNotification::QoSProperties initial_qos;
    CosNotification::AdminProperties initial_admin;

    CosNotifyChannelAdmin::EventChannel_var ec =
      notify_factory->create_channel (initial_qos,
      initial_admin,
      id);

    if (CORBA::is_nil (ec.in())) {
      std::cerr << "Unable to create event channel" << std::endl;
      return;
    }


    CosNaming::Name name(1);
    name.length(1);
    name[0].id = CORBA::string_dup("MyEventChannel");

    naming_context->rebind(name, ec.in());

    CosNotifyChannelAdmin::AdminID adminid;
    CosNotifyChannelAdmin::InterFilterGroupOperator ifgop =
      CosNotifyChannelAdmin::AND_OP;

    CosNotifyChannelAdmin::SupplierAdmin_var supplier_admin =
      ec->new_for_suppliers (ifgop, adminid);

    if (CORBA::is_nil (supplier_admin.in())) {
      std::cerr << "Unable to find supplier admin" << std::endl;
    }

    CosNotifyChannelAdmin::ProxyID supplieradmin_proxy_id;

    CosNotifyChannelAdmin::ProxyConsumer_var proxy_consumer =
      supplier_admin->obtain_notification_push_consumer(
      CosNotifyChannelAdmin::STRUCTURED_EVENT,
      supplieradmin_proxy_id);

    StructuredEventSupplier_i *servant =
      new StructuredEventSupplier_i(orb_.in());

    PortableServer::ObjectId_var oid = poa->activate_object(servant);
    CORBA::Object_var supplier_obj = poa->id_to_reference(oid.in());
    CosNotifyComm::StructuredPushSupplier_var supplier =
      CosNotifyComm::StructuredPushSupplier::_narrow(supplier_obj.in());

    consumer_proxy_ =
      CosNotifyChannelAdmin::StructuredProxyPushConsumer::
      _narrow(proxy_consumer.in());

    if (CORBA::is_nil (consumer_proxy_.in())) {
      std::cerr << "Unable to find structured proxy push consumer" << std::endl;
    }

    consumer_proxy_->connect_structured_push_supplier(supplier.in());

  }
  catch(const CORBA::Exception& ex) {
    std::cerr << ex << std::endl;
  }

}


// Implementation skeleton destructor
Messenger_i::~Messenger_i (void)
{
}

CORBA::Boolean Messenger_i::send_message (
                                          const char * user_name,
                                          const char * subject,
                                          char *& message
                                          )
{

  std::cout << "Message from: " << user_name << std::endl;
  std::cout << "Subject:      " << subject << std::endl;
  std::cout << "Message:      " << message << std::endl;

  try
  {

    // Event Definition
    CosNotification::StructuredEvent event;

    event.header.fixed_header.event_type.domain_name =
      CORBA::string_dup("OCI_TAO");
    // string
    event.header.fixed_header.event_type.type_name =
      CORBA::string_dup("examples");
    // string
    event.header.fixed_header.event_name =
      CORBA::string_dup("myevent");

    // sequence<Property>: string name, any value
    event.filterable_data.length (1);
    event.filterable_data[0].name = CORBA::string_dup("From");
    event.filterable_data[0].value <<= (const char *)user_name;
    event.filterable_data.length (2);
    event.filterable_data[1].name = CORBA::string_dup("Subject");
    event.filterable_data[1].value <<= (const char *)subject;
    event.filterable_data.length (3);
    event.filterable_data[2].name = CORBA::string_dup("Message");
    event.filterable_data[2].value <<= (const char *)message;

    consumer_proxy_->push_structured_event(event);
  }

  catch(const CosNotifyComm::InvalidEventType&) {
    std::cerr << "Invalid Event Type Exception " << std::endl;
    return 1;
  }

  catch(const CORBA::Exception& ex) {
    std::cerr << ex << std::endl;
    return 1;
  }
  return 0;
}
