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

#include <OB/CORBA.h>
#include <OB/Util.h>
#include <OB/Properties.h>

#include <OB/OBEventChannelFactory.h>
#include <OB/OBTypedEventChannelFactory.h>

#include <stdlib.h>

#include <Config.h> // Make sure that the compiler complains if the
                    // configuration doesn't match

static void
usage(const char* progName)
{
    cerr << "Usage:\n";
    cerr << progName << " [options] command\n"
	"\n"
	"Options:\n"
	"-h, --help             Show this message.\n"
	"-v, --version          Show version number.\n"
        "-t, --typed-service    Admin for typed event service.\n"
        "-u, --untyped-service  Admin for untyped event service [default].\n"
	"\n"
	"Commands:\n"
	"create channel-id      Create a new event channel.\n"
	"destroy channel-id     Destroy an event channel.\n"
	"list                   Show the active event channels.\n"
	"shutdown               Terminate the event service.\n"
	;
}

int
main(int argc, char** argv)
{
    try
    {
	int i;
	bool typedService = false;

	//
	// Create ORB
	//
	CORBA_ORB_var orb = CORBA_ORB_init(argc, argv);

        //
	// Get options
	//
	for(i = 1 ; i < argc && *argv[i] == '-' ; i++)
	{
	    if(strcmp(argv[i], "--help") == 0 ||
	       strcmp(argv[i], "-h") == 0)
	    {
		usage(argv[0]);
		return 0;
	    }
	    else if(strcmp(argv[i], "--version") == 0 ||
		    strcmp(argv[i], "-v") == 0)
	    {
		cerr << "Event Service" << OBVersion << endl;
		return 0;
	    }
	    else if(strcmp(argv[i], "--untyped-service") == 0 ||
		    strcmp(argv[i], "-u") == 0)
	    {
	    }
	    else if(strcmp(argv[i], "--typed-service") == 0 ||
		    strcmp(argv[i], "-t") == 0)
            {
                typedService = true;
            }
	    else
	    {
		cerr << argv[0] << ": unknown option `"
		     << argv[i] << "'\n" << endl;
		usage(argv[0]);
		return 1;
	    }
	}

        if(i == argc)
        {
            usage(argv[0]);
            return 1;
        }

        const char* serviceName
            = typedService ? "TypedEventChannelFactory" : "EventChannelFactory";
        
        CORBA_Object_var obj;
        try
	{
            obj =
                orb -> resolve_initial_references(serviceName);
        }
        catch(CORBA_ORB::InvalidName&)
        {
        }

        if(CORBA_is_nil(obj))
        {
            cerr << "No `" << serviceName << "' initial reference." << endl;
            exit(1);
        }

        if(typedService)
        {
            OBTypedEventChannelFactory_TypedEventChannelFactory_var f =
                OBTypedEventChannelFactory_TypedEventChannelFactory::_narrow(
                    obj);
            if(CORBA_is_nil(f))
            {
                cerr << "`" << serviceName << "' initial reference is invalid."
                     << endl;
                exit(1);
            }

            if(i + 1 < argc && strcmp(argv[i], "create") == 0)
            {
                try
                {
                    CosTypedEventChannelAdmin_TypedEventChannel_var channel =
                        f -> create_channel(argv[i + 1]);
                }
                catch(const OBEventChannelFactory_ChannelAlreadyExists&)
                {
                    cerr << "Channel `" << argv[i + 1] << "' already exists"
                         << endl;
                    exit(1);
                }
            }
            else if(i + 1 < argc && strcmp(argv[i], "destroy") == 0)
            {
                try
                {
                    CosTypedEventChannelAdmin_TypedEventChannel_var channel =
                        f -> get_channel_by_id(argv[i + 1]);
                    channel -> destroy();
                }
                catch(const OBEventChannelFactory_ChannelNotAvailable&)
                {
                    cerr << "Channel `" << argv[i + 1] << "' not found"
                         << endl;
                    exit(1);
                }
            }
            else if(i < argc && strcmp(argv[i], "list") == 0)
            {
                OBEventChannelFactory_ChannelIdSeq_var ids =
                    f -> get_channels();
                if(ids -> length() == 0)
                    cout << "No active channels" << endl;
                else
                {
                    for(CORBA_ULong j = 0 ; j < ids -> length() ; j++)
                        cout << ids[j] << endl;
                }
            }
            else if(i < argc && strcmp(argv[i], "shutdown") == 0)
            {
                try
                {
                    f -> shutdown();
                }
                catch(const CORBA_TRANSIENT&)
                {
                    //
                    // This call will deactivate the server and thus
                    // throw an exception.
                    //
                }
            }
            else
                usage(argv[0]);
        }
        else
        {
            OBEventChannelFactory_EventChannelFactory_var f =
                OBEventChannelFactory_EventChannelFactory::_narrow(obj);
            if(CORBA_is_nil(f))
            {
                cerr << "`" << serviceName << "' initial reference is invalid."
                     << endl;
                exit(1);
            }

            if(i + 1 < argc && strcmp(argv[i], "create") == 0)
            {
                try
                {
                    CosEventChannelAdmin_EventChannel_var channel =
                        f -> create_channel(argv[i + 1]);
                }
                catch(const OBEventChannelFactory_ChannelAlreadyExists&)
                {
                    cerr << "Channel `" << argv[i + 1] << "' already exists"
                         << endl;
                    exit(1);
                }
            }
            else if(i + 1 < argc && strcmp(argv[i], "destroy") == 0)
            {
                try
                {
                    CosEventChannelAdmin_EventChannel_var channel =
                        f -> get_channel_by_id(argv[i + 1]);
                    channel -> destroy();
                }
                catch(const OBEventChannelFactory_ChannelNotAvailable&)
                {
                    cerr << "Channel `" << argv[i + 1] << "' not found"
                         << endl;
                    exit(1);
                }
            }
            else if(i < argc && strcmp(argv[i], "list") == 0)
            {
                OBEventChannelFactory_ChannelIdSeq_var ids =
                    f -> get_channels();
                if(ids -> length() == 0)
                    cout << "No active channels" << endl;
                else
                {
                    for(CORBA_ULong j = 0 ; j < ids -> length() ; j++)
                        cout << ids[j] << endl;
                }
            }
            else if(i < argc && strcmp(argv[i], "shutdown") == 0)
            {
                try
                {
                    f -> shutdown();
                }
                catch(const CORBA_TRANSIENT&)
                {
                    //
                    // This call will deactivate the server and thus
                    // throw an exception.
                    //
                }
            }
            else
                usage(argv[0]);
        }
    }
    catch(const CORBA_SystemException& ex)
    {
        OBPrintException(ex);
        return 1;
    }
    return 0;
}
