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

#include <OB/CORBA.h>
#include <OB/Util.h>
#include <OB/CosEventChannelAdmin.h>
#include <OB/OBEventChannelFactory.h>
#include <OB/CosEventComm_skel.h>

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

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

class PushSupplier_impl : public CosEventComm_PushSupplier_skel
{
    CosEventComm_PushConsumer_var consumer_;

public:

    PushSupplier_impl(CosEventComm_PushConsumer_ptr);
    ~PushSupplier_impl();

    void disconnect_push_supplier();

    int run();
};

PushSupplier_impl::PushSupplier_impl(CosEventComm_PushConsumer_ptr consumer)
    : consumer_(CosEventComm_PushConsumer::_duplicate(consumer))
{
    assert(!CORBA_is_nil(consumer_));
}

PushSupplier_impl::~PushSupplier_impl()
{
    consumer_ -> disconnect_push_consumer();
}

void
PushSupplier_impl::disconnect_push_supplier()
{
    consumer_ = CosEventComm_PushConsumer::_nil();
}

//
// Provide date and time
//
int
PushSupplier_impl::run()
{
    //
    // Main loop
    //
    while(true)
    {
	char str[256];
	time_t clock;

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

	try
	{
	    CORBA_Any any;

	    any <<= CORBA_string_dup(str);
	    consumer_ -> push(any);
	}
	catch(CORBA_SystemException& ex)
	{
	    OBPrintException(ex);
	    return 1;
	}

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

    return 0;
}

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);
	
        //
        // 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("EventChannelFactory");
	}
	catch(const CORBA_ORB::InvalidName&)
	{
	    cerr << argv[0] << ": can't resolve `EventChannelFactory'" << endl;
	    return 1;
	}
	
	if(CORBA_is_nil(objF))
	{
	    cerr << argv[0]
                 << ": `EventChannelFactory' is a nil object reference"
		 << endl;
	    return 1;
	}
	
	OBEventChannelFactory_EventChannelFactory_var f =
            OBEventChannelFactory_EventChannelFactory::_narrow(objF);
	
	if(CORBA_is_nil(f))
	{
	    cerr << argv[0]
		 << ": `EventChannelFactory' is not an "
                 << "EventChannelFactory 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;
        }
	
        CosEventChannelAdmin_EventChannel_var e =
            CosEventChannelAdmin_EventChannel::_narrow(obj);
	
        if(CORBA_is_nil(e))
        {
            cerr << argv[0]
                 << ": `" << ecName
                 << "' is not an EventChannel object reference"
                 << endl;
            return 1;
        }
	
	//
	// Get ProxyPushConsumer.
	//
	CosEventChannelAdmin_SupplierAdmin_var supplierAdmin =
	    e -> for_suppliers();
	CosEventChannelAdmin_ProxyPushConsumer_var consumer =
	    supplierAdmin -> obtain_push_consumer();
	
	//
	// Connect implementation to ProxyPushConsumer.
	//
	PushSupplier_impl* supplier = new PushSupplier_impl(consumer);
	CosEventComm_PushSupplier_var dummy = supplier;
	consumer -> connect_push_supplier(CosEventComm_PushSupplier::_nil());
	
	if(supplier -> run() == 1)
	    return 1;
    }
    catch(CORBA_SystemException& ex)
    {
        OBPrintException(ex);
        return 1;
    }
 
    return 0;
}
