//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / OVOPS++
//
//File: conduittest.cpp
//
//Version: $Revision: 1.8 $
//
//State: $State: Exp $
//
//Date: $Date: 1999/01/25 07:10:13 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Timo Pärnänen
//
//Description:
//      A program to test the conduits
//
//Copyright:
//
//
//Licence:
//
//
//History: 

#include <typeinfo>
#include <iostream.h>
#include <string>

#include "pf/system.h"
#include "pf/conduit.h"
#include "pf/protocol.h"
#include "pf/transp.h"
#include "pf/factory.h"
#include "pf/mux.h"
//#include "common/heapstat.h"

#include "pftest.h"

//HeapStats stat;

//------------------------------------------------------------------------

int main(int argc, char *argv[])
{
//    stat.reset();

    int counter = 1;
    int data_counter = 1;

    if (argc > 3)
    {
        cerr << "Usage: " << argv[0]
             << " [rounds]" << endl;
        exit(0);
    }
    if (argc > 2)
    {
        data_counter = atoi(argv[2]);
    }    
    if (argc > 1)
    {
        counter = atoi(argv[1]);
    }

    // Initialize variables
    pfId id = 0;
    pfKey key = 1;
    pfKey maxValue = 1000;
    
    // Create implementations
    pfTestUpAdapter *upAdapter = new pfTestUpAdapter(data_counter); // COUNTER
    pfTestDownAdapter *downAdapter = new pfTestDownAdapter;
    
    pfTestUpProtocol *upProto = new pfTestUpProtocol;
    pfTestDownProtocol *downProto = new pfTestDownProtocol;

    // Create conduit proxies
    pfConduit upAdapterProxy(upAdapter);
    pfConduit downAdapterProxy(downAdapter);

    string keyName("testKey");

    pfConduit upMuxProxy = pfMux::createMux(maxValue, keyName);
    pfConduit downMuxProxy = pfMux::createMux(maxValue, keyName);

    pfConduit upProtoProxy(upProto);
    pfConduit downProtoProxy(downProto);

    // Set ids
    upAdapterProxy.setId(id);
    downAdapterProxy.setId(id);    

    upMuxProxy.setId(id);
    downMuxProxy.setId(id);    

    upProtoProxy.setId(id);
    downProtoProxy.setId(id);


    // Create prototype (gain)
    upProtoProxy.connectToA(downProtoProxy);
    downProtoProxy.connectToB(upProtoProxy);
    
    // Factory
    pfConduit factoryProxy = pfFactory::createFactory(downProtoProxy);
    factoryProxy.setId(id);

    // Connect conduits
    upAdapterProxy.connectToA(upMuxProxy);

    upMuxProxy.connectToA(upAdapterProxy);    
    upMuxProxy.connectToB(factoryProxy);
    
    factoryProxy.connectToB(upMuxProxy);
    factoryProxy.connectToA(downMuxProxy);

    downMuxProxy.connectToB(factoryProxy);
    downMuxProxy.connectToA(downAdapterProxy);

    downAdapterProxy.connectToA(downMuxProxy);    

    upAdapterProxy.setTraceOn();
    downAdapterProxy.setTraceOn();    

    upMuxProxy.setTraceOn();
    downMuxProxy.setTraceOn();    
    
    upProtoProxy.setTraceOn();
    downProtoProxy.setTraceOn();

    factoryProxy.setTraceOn();

//    pfTestSETUPind *messenger1 = new pfTestSETUPind;
//    messenger1->setKey(key);
//    pfMsgTransporter *message1 =
//        pfMsgTransporter::createMsgTransporter(messenger1);
//    downAdapterProxy.accept(message1);
//    pfSystem::instance()->run();
    

    int i;
    for (i=0; i<counter; i++)
    {
        cout << "i = " << i << endl;

        pfTestSETUPind *messenger1 = new pfTestSETUPind;
        messenger1->setKey(key+i);

        pfTestVisitor *visit1 = new pfTestVisitor(messenger1);
        downAdapterProxy.accept(visit1);
        pfSystem::instance()->run();
        
        cout << "----------------(SetUp Ok)---------------------" << endl;

        pfTestDATAind *messenger2 = new pfTestDATAind;
        messenger2->setKey(key+i);
        pfTestVisitor *visit2 = new pfTestVisitor(messenger2);
        downAdapterProxy.accept(visit2);        
        pfSystem::instance()->run();
        
        cout << "----------------(Data Ok)----------------------" << endl;

        pfTestRELEASEind *messenger3 = new pfTestRELEASEind;
        messenger3->setKey(key+i);
        pfTestVisitor *visit3 = new pfTestVisitor(messenger3);
        downAdapterProxy.accept(visit3);
        pfSystem::instance()->run();

        cout << "---------------(Release Ok)--------------------" << endl;
    }

//    pfTestRELEASEind *messenger3 = new pfTestRELEASEind;
//    messenger3->setKey(key);
//    downAdapterProxy.toA(messenger3);
//    pfSystem::instance()->run();

    
    cout << "DISCONNECT !!" << endl;

    upAdapterProxy.disconnect();
    downAdapterProxy.disconnect();    

    upMuxProxy.disconnect();
    downMuxProxy.disconnect();    

    upProtoProxy.disconnect();
    downProtoProxy.disconnect();
    
    factoryProxy.disconnect();

    cout << "END OF TEST !!" << endl;
//    stat.report();
    
#if 0
#include <vector>
    vector<string> a(argv + 1, argv + argc);
    pfSystem::instance()->startProgram(argv[0], a);
#endif
    return 0;
}

