/*
 * Utility class for the news notification service example.  This class
 * provides access to a single event channel created with persistent
 * ConnectionReliability and EventReliability.
 */

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

/*
 * @func Constructs a ChannelUtil object
 * @parm | orbVar | a reference to the ORB
 * @rdesc output and exit on error
 */
ChannelUtil::ChannelUtil (CORBA::ORB_ptr orb)
   : orbVar_ (CORBA::ORB::_duplicate (orb))
   , channelFactoryVar_ (0)
   , channelVar_ (0)
{
  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 event channel factory.
  CORBA::Object_var objVar =
    orbVar_->resolve_initial_references (ACE_TEXT ("NotificationService"));
  if (CORBA::is_nil (objVar.in ()))
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Could not resolve to the notification service\n")));
      throw TestException ();
    }
  channelFactoryVar_ =
    CosNotifyChannelAdmin::EventChannelFactory::_narrow (objVar.in ());
  if (CORBA::is_nil (channelFactoryVar_.in ()))
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Could not resolve to the notify channel admin\n")));
      throw TestException ();
    }
}

/*
 * @func Returns a reference to the event channel
 * @rdesc Reference to the event channel
 */
CosNotifyChannelAdmin::EventChannel_ptr
ChannelUtil::getChannel (void)
{
  // Create the channel if required.
  if (CORBA::is_nil (channelVar_.in ()))
    {
      // Try to obtain channel ID 0.
      try
        {
          channelVar_ = channelFactoryVar_->get_event_channel (0);

          ACE_DEBUG ((LM_INFO, ACE_TEXT ("INFO: Found channel with id 0\n")));
        }
      catch (const CosNotifyChannelAdmin::ChannelNotFound &)
        {
          // No action needed at this point.
        }
    }

  // If it could not be found, create a new channel.
  if (CORBA::is_nil (channelVar_.in ()))
    {
      CosNotifyChannelAdmin::ChannelID id;
      CosNotification::QoSProperties qos = CosNotification::QoSProperties (2);
      CosNotification::AdminProperties adm = CosNotification::AdminProperties (0);

      qos.length (2);
      qos[0].name =
        CORBA::String_var (CORBA::string_dup (CosNotification::ConnectionReliability));
      qos[0].value <<= CosNotification::Persistent;
      qos[1].name =
        CORBA::String_var (CORBA::string_dup (CosNotification::EventReliability));
      qos[1].value <<= CosNotification::Persistent;

      try
        {
          channelVar_ = channelFactoryVar_->create_channel (qos, adm, id);
          ACE_DEBUG ((LM_INFO, ACE_TEXT ("Created channel with id %i\n"), id));
        }
      catch (const CORBA::Exception &)
        {
          ACE_ERROR ((LM_ERROR, ACE_TEXT ("Failed to create the event channel\n")));
          throw;
        }
    }

  return CosNotifyChannelAdmin::EventChannel::_duplicate (channelVar_.in ());
}

/*
 * @func Prints an event's details to a string.
 * @parm | event | the event to display
 * @parm | buffer | a suitably-allocated character array
 */
void
ChannelUtil::printEvent (const CosNotification::StructuredEvent &event, char *buffer)
{
  const char *eventType = event.header.fixed_header.event_type.type_name;

  if (ACE_OS::strcmp (eventType, ACE_TEXT ("Weather")) == 0)
    {
      const char *location;
      const char *conditions;

      event.filterable_data[1].value >>= location;
      event.remainder_of_body >>= conditions;

      ACE_OS::strcpy (buffer, location);
      ACE_OS::strcat (buffer, ACE_TEXT (" - "));
      ACE_OS::strcat (buffer, conditions);
    }
  else if (ACE_OS::strcmp (eventType, ACE_TEXT ("StockQuote")) == 0)
    {
      int priority;
      const char *news;

      event.header.variable_header[1].value >>= priority;
      event.remainder_of_body >>= news;

      ACE_OS::sprintf (buffer, ACE_TEXT ("(Priority %i) - %s"), priority, news);
    }
  else
    {
      ACE_OS::strcpy (buffer, ACE_TEXT ("<Could not display event: unknown type: "));
      ACE_OS::strcat (buffer, eventType);
      ACE_OS::strcat (buffer, ACE_TEXT (">"));
    }
}
