// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#include <OB/CORBA.h>
#include <OB/Util.h>
#include <OB/CosTypedEventChannelAdmin.h>
#include <OB/OBTypedEventChannelFactory.h>
#include <OB/CosTypedEventComm_skel.h>

#include <TimerUpdate.h>

#include <stdlib.h>

#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#endif

#include <stdio.h>
#include <time.h>

static void
usage(const char* progName)
{
    cerr << "\nUsage:\n";
    cerr << progName
         << " [options] event-channel-name\n"
        "\n"
        "Options:\n"
        "-h, --help             Show this message.\n"
        ;
}

int
main(int argc, char* argv[], char*[])
{
    try
    {
        //
        // Create ORB.
        //
        CORBA_ORB_var orb = CORBA_ORB_init(argc, argv);

	orb -> conc_model(CORBA_ORB::ConcModelBlocking);
	
        //
        // Parse command line arguments.
        //
        const char* ecName = 0;

        for(int i = 1; i < argc; ++i)
        {
            if(*argv[i] == '-')
            {
                if(strcmp(argv[i], "--help") == 0 ||
                   strcmp(argv[i], "-h") == 0)
                {
                    usage(argv[0]);
                    return 0;
                }
                else
                {
                    cerr << argv[0] << ": unknown option `"
                         << argv[i] << endl;
                    usage(argv[0]);
                    return 1;
                }
            }
            else if(!ecName)
                ecName = argv[i];
            else
            {
                usage(argv[0]);
                return 0;
            }
        }

        if (!ecName)
        {
            usage(argv[0]);
            return 0;
        }
	
	//
	// Get event channel factory.
	//
	CORBA_Object_var objF;
	
	try
	{
	    objF =
                orb -> resolve_initial_references("TypedEventChannelFactory");
	}
	catch(const CORBA_ORB::InvalidName&)
	{
	    cerr << argv[0] << ": can't resolve `TypedEventChannelFactory'"
                 << endl;
	    return 1;
	}
	
	if(CORBA_is_nil(objF))
	{
	    cerr << argv[0]
                 << ": `TypedEventChannelFactory' is a nil object reference"
		 << endl;
	    return 1;
	}
	
	OBTypedEventChannelFactory_TypedEventChannelFactory_var f =
            OBTypedEventChannelFactory_TypedEventChannelFactory::_narrow(
                objF);
	
	if(CORBA_is_nil(f))
	{
	    cerr << argv[0]
		 << ": `TypedEventChannelFactory' is not an "
                 << "TypedEventChannelFactory object reference"
		 << endl;
	    return 1;
	}

	//
	// Get event channel.
	//
	CORBA_Object_var obj;

        try
        {
            obj = f -> get_channel_by_id(CORBA_string_dup(ecName));
        }
        catch(OBEventChannelFactory_ChannelNotAvailable&)
        {
            try
            {
                obj = f -> create_channel(CORBA_string_dup(ecName));
                cerr << argv[0] << ": `Channel " << ecName << "' created"
                     << endl;
            }
            catch(OBEventChannelFactory_ChannelAlreadyExists&)
            {
            }
        }

	if(CORBA_is_nil(obj))
	{
	    cerr << argv[0] << ": `" << ecName << "' is a nil object reference"
		 << endl;
	    return 1;
	}
	
	CosTypedEventChannelAdmin_TypedEventChannel_var e =
	    CosTypedEventChannelAdmin_TypedEventChannel::_narrow(obj);
	
	if(CORBA_is_nil(e))
	{
	    cerr << argv[0]
		 << ": `" << ecName
                 << "' is not an EventChannel object reference"
		 << endl;
	    return 1;
	}

	//
	// Get TypedProxyPushConsumer.
	//
	CosTypedEventChannelAdmin_TypedSupplierAdmin_var supplierAdmin =
	    e -> for_suppliers();
	CosTypedEventChannelAdmin_TypedProxyPushConsumer_var consumer;
	try
	{
	    consumer = supplierAdmin ->
		obtain_typed_push_consumer("IDL:event/TimerUpdate:1.0");
	}
	catch(const CosTypedEventChannelAdmin_InterfaceNotSupported&)
	{
	    cerr << "InterfaceNotSupported" << endl;
	    return 1;
	}

	CORBA_Object_ptr typedConsumer = consumer -> get_typed_consumer();

	TimerUpdate_var timer = TimerUpdate::_narrow(typedConsumer);
	assert(!CORBA_is_nil(timer));

	while(true)
	{
	    char str[256];
	    time_t clock;

	    clock = time(0);
	    sprintf(str, "PushSupplier says: %s", ctime(&clock));
	    str[strlen(str) - 1] = 0;

	    try
	    {
		timer -> time_update(str);
	    }
	    catch(CORBA_SystemException& ex)
	    {
		OBPrintException(ex);
		return 1;
	    }

    #ifdef WIN32
	    Sleep(1000);
    #else
	    sleep(1);
    #endif
	}

	consumer -> disconnect_push_consumer();
    }
    catch(CORBA_SystemException& ex)
    {
        OBPrintException(ex);
        return 1;
    }
 
    return 0;
}
