/*
 * Base class for all news publishers.
 */

#include "NewsPublisher.h"
#include "Common/ObjectAdapter.h"

NewsPublisher::NewsPublisher (CORBA::ORB_ptr orb)
  : orbVar_ (CORBA::ORB::_duplicate (orb))
  , util_ (orb)
  , supplierVar_ (0)
  , proxyVar_ (0)
  , eventCount_ (100)
  , maxDelay_ (0L)
{
  if (CORBA::is_nil (orbVar_.in ()))
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Passed a null ORB reference\n")));
      throw TestException ();
    }

  // Obtain a reference to the root POA.
  CORBA::Object_var objVar =
    orbVar_->resolve_initial_references (ACE_TEXT ("RootPOA"));
  PortableServer::POA_var rootPoaVar =
    PortableServer::POA::_narrow (objVar.in ());

  // Obtain a reference to the POA manager and activate it.
  PortableServer::POAManager_var poaManagerVar =
    rootPoaVar->the_POAManager ();
  poaManagerVar->activate ();

  // Create the CORBA object for this publisher.
  objVar = _this ();
  supplierVar_ =
    CosNotifyComm::StructuredPushSupplier::_narrow (objVar.in ());

  // Seed the random number generator.
  srand ((unsigned) time (0));
}

void
NewsPublisher::connectToChannel (void)
{
  // Obtain a reference to the channel.
  CosNotifyChannelAdmin::EventChannel_var channelVar = util_.getChannel ();

  // Obtain a reference to the default supplier admin.
  CosNotifyChannelAdmin::SupplierAdmin_var adminVar;
  try
    {
      adminVar = channelVar->default_supplier_admin ();
      ACE_DEBUG ((LM_INFO, ACE_TEXT ("Obtained default supplier admin\n")));
    }
  catch (const CORBA::Exception &)
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Failed to obtain default supplier admin\n")));
      throw;
    }

  // Obtain a proxy consumer.
  CosNotifyChannelAdmin::ProxyConsumer_var pcVar;
  try
    {
      CosNotifyChannelAdmin::ProxyID pid;
      CosNotifyChannelAdmin::ClientType type = CosNotifyChannelAdmin::STRUCTURED_EVENT;

      pcVar = adminVar->obtain_notification_push_consumer (type, pid);
      if (CORBA::is_nil (pcVar.in ()))
        {
          ACE_ERROR ((LM_ERROR, ACE_TEXT ("Obtained a null proxy consumer\n")));
          throw TestException ();
       }
     }
  catch (const CORBA::Exception &)
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Failed to obtain a proxy consumer\n")));
      throw;
    }

  // Narrow to a structured proxy push consumer.
  proxyVar_ =
    CosNotifyChannelAdmin::StructuredProxyPushConsumer::_narrow (pcVar.in ());
  if (CORBA::is_nil (proxyVar_.in ()))
    {
      ACE_ERROR ((LM_ERROR,
                  ACE_TEXT ("Narrowed to a null structured proxy push consumer\n")));
      throw TestException ();
    }

  // Connect.
  try
    {
      proxyVar_->connect_structured_push_supplier (supplierVar_.in ());
      ACE_DEBUG ((LM_INFO, ACE_TEXT ("Connected supplier to proxy\n")));
    }
  catch (const CORBA::Exception &)
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Failed to connect supplier to proxy\n")));
      throw;
    }
}

void
NewsPublisher::broadcast (void)
{
  char message[512];

  for (int i = 0; i < eventCount_; i++)
    {
      CosNotification::StructuredEvent_var eventVar = createNextEvent ();
      try
        {
          proxyVar_->push_structured_event (eventVar.in ());

          ACE_OS::memset (message, 0, sizeof (message) / sizeof (char));
          util_.printEvent (eventVar.in (), message);
          ACE_DEBUG ((LM_INFO, ACE_TEXT ("Sent message: %s\n"), message));

          delay ();
        }
      catch (const CORBA::Exception &)
        {
          ACE_ERROR ((LM_ERROR, ACE_TEXT ("Failed to send event\n")));
          break;
        }
   }
}

void
NewsPublisher::delay (void)
{
  long delay = rand () % maxDelay_;
  ACE_Time_Value atv;
  atv.msec (delay);

  ACE_OS::sleep (atv);
}

void
NewsPublisher::disconnect_structured_push_supplier (void)
{
}

void
NewsPublisher::subscription_change (const CosNotification::EventTypeSeq &/*added*/,
                                    const CosNotification::EventTypeSeq &/*removed*/)
{
}
