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

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

#include <Peer_impl.h>

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

#ifdef HAVE_FSTREAM
#   include <fstream>
#else
#   include <fstream.h>
#endif

int
main(int argc, char* argv[], char*[])
{
    try
    {
	//
	// Create ORB and BOA
	//
	CORBA_ORB_var orb = CORBA_ORB_init(argc, argv);
	CORBA_BOA_var boa = orb -> BOA_init(argc, argv);
	
	//
	// Set the concurrency model
	//
#ifdef HAVE_JTC
	if(orb -> conc_model() != CORBA_ORB::ConcModelThreaded ||
	   (boa -> conc_model() != CORBA_BOA::ConcModelThreadPerRequest &&
	    boa -> conc_model() != CORBA_BOA::ConcModelThreadPool))
	{
	    orb -> conc_model(CORBA_ORB::ConcModelReactive);
	    boa -> conc_model(CORBA_BOA::ConcModelReactive);
	}
#else
	orb -> conc_model(CORBA_ORB::ConcModelReactive);
	boa -> conc_model(CORBA_BOA::ConcModelReactive);
#endif
	
	//
	// Create implementation object
	//
	Peer_var p2 = new Peer_impl;
	
	//
	// Get other object
	//
	const char* refFile = "Peer.ref";
	ifstream in; // Must use open(name), not ifstream in(name) (VC++ bug)
	in.open(refFile);
	if(in.fail())
	{
	    cerr << argv[0] << ": can't open `" << refFile << "': "
		 << strerror(errno) << endl;
	    return 1;
	}
	
	char s[1000];
	in >> s;
	
	CORBA_Object_var obj = orb -> string_to_object(s);
	assert(!CORBA_is_nil(obj));

	Peer_var p1 = Peer::_narrow(obj);
	assert(!CORBA_is_nil(p1));
	
	//
	// Initialize the servers so that incoming requests are
	// handled from this point on
	//
	boa -> init_servers();
	
	while(true)
	{
	    //
	    // Start recursive decrement
	    //
	    cout << "Enter a number (0 to exit): ";
	    CORBA_Long value;
	    cin >> value;
	    
	    if(value <= 0)
		break;
	    
	    //
	    // Run demo
	    //
	    timeval tv = OBTimerList::timeNow();
	    p1 -> decrement(value, p2);
	    tv = OBTimerList::timeSub(OBTimerList::timeNow(), tv);
	    cout << "Time needed: "
		 << ((double)tv.tv_sec + (double)tv.tv_usec / 1000000.0)
		 << endl;
	}
	
	//
	// Deactivate implementation
	//
	boa -> deactivate_impl(CORBA_ImplementationDef::_nil());
    }
    catch(CORBA_SystemException& ex)
    {
	OBPrintException(ex);
	return 1;
    }

    return 0;
}
