//
// Derived from the Hello example of OmniBroker 1.0
//

#include <typeinfo>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>	// strerror
#include <errno.h>	// errno

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

#include <OB/CORBA.h>
#include <OB/Util.h>
#include "loopconduit_impl.h"
#include "democlasses.h"
#include "pf/system.h"
#include "pf/transp.h"
#include "pf/mux.h"


loopAdapter *setupConduits(void);


int main(int argc, char* argv[], char*[])
{
    pfSystem::init(argc, argv);
    try
    {
	//
	// Create implementation object
	//
        loopAdapter *obj = setupConduits();
	loopConduit_var p(obj);
	
	//
	// Save reference
	//
	CORBA_String_var s = pfSystem::instance()->getORB()->object_to_string(p);
	const char* refFile = "Loop.ref";

        //
        // NOTE: use C FILEs rather than C++ file streams, because the
        // latter don't work with g++ when RTTI is in use
        //
        FILE *fp = fopen(refFile, "w");
        if(fp == 0)
	{
	    cerr << argv[0] << ": can't open `" << refFile << "': "
		 << strerror(errno) << endl;
	    return 1;
	}
	
        fprintf(fp, "%s\n", s.in());
        fclose(fp);
	
	//
	// Run implementation (DON'T call impl_is_ready!)
	//
        pfSystem::instance()->run();
    }
#ifdef __GNUG__
    catch(CORBA_COMM_FAILURE& ex)
#else
    catch(CORBA_SystemException& ex)
#endif
    {
	OBPrintException(ex);
	return 1;
    }

    return 0;
}


//
// Function: setupConduits
//
// Description:
//     Instantiates the conduit tree for this demo server:
//
//
//            ___ IDL for inject()
//      _______|______
//      \ loopAdapter/
//       ------------       ---------------------
//             |            |                   |
//      _______|____________|______             |
//      \           Mux           /             |
//       -------------------------              |
//                   |                          |
//                   |                          |
//            ---------------            ---------------
//            |loopProtocol1|            |loopProtocol2|
//            ---------------            ---------------
//                   |                          |
//                   |                          |
//                   ----------------------------
//
//     The loopMessage instances are injected by the loopAdapter class,
//     when a client calls the inject method of its IDL interface. The
//     messages will get forwarded in the loopProtocol loop until the
//     they have been forwared for the number of times the client had
//     requested.
//

loopAdapter *setupConduits(void)
{
    int counter = NUMBER_OF_TEST_ROUNDS;
    int timeout = DEFAULT_TIMEOUT;

    loopAdapter *loop = new loopAdapter;
    string nullName("");
    pfConduit muxProxy = pfMux::createMux(100, nullName);
    loopState *state = new loopState;
    loopProtocol *proto1 = new loopProtocol(counter, timeout);
    loopProtocol *proto2 = new loopProtocol(0, 0);

    proto1->changeState(state);
    proto2->changeState(state);

    pfConduit l1(loop);
    pfConduit p1(proto1);
    pfConduit p2(proto2);

    p1.setId(1);
    p2.setId(2);

    l1.connectToA(muxProxy);
    muxProxy.connectToA(p1);
    p1.connectToA(muxProxy);
    p1.connectToB(p2);
    p2.connectToA(p1);
    p2.connectToB(muxProxy);

    pfInstallTransporter i =
        pfInstallTransporter::createInstallTransporter(l1);
    pfInstallTransporter j =
        pfInstallTransporter::createInstallTransporter(p2);
    muxProxy.accept(&i);
    muxProxy.accept(&j);

    return loop;
}
