//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / OVOPS++
//
//File: ss7testmain.cpp
//
//Version: $Revision: 1.12 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/10/08 14:19:28 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Timo Pärnänen
//
//Description:
//      Mainfile for testing SCCP protocol
//
//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/mux.h"
#include "pf/bytes.h"
#include "pf/debug.h"
#include "common/ss7configure.h"

#include "iface/sccpif/sccpdownprimitives.h"
#include "iface/naalif/naaldownprimitives.h"

#include "ss7test.h"
#include "protocol/sccp/sccpprotocol.h"
#include "protocol/mtp3/mtp3protocol.h"
#include "protocol/mtp3/mtp3config.h"

#include "protocol/saal/saalnnilink.h"

const string callingGT_1("1234");
const string calledGT_1("9876");
const string origPC_1("10");
const string destPC_1("15");

const string callingGT_2(calledGT_1);
const string calledGT_2(callingGT_1);
const string origPC_2(destPC_1);
const string destPC_2(origPC_1);

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

void printUsage(char *name_)
{
    cerr << endl;
    cerr << "Usage: " << name_ << " <c 1|2> <v VCI> [p PORT] [d] ";
    cerr << "[-ORBnaming `cat /work/Naming/Naming.ior`]" << endl;
    cerr << "<c 1|2]>  = Configuration 1 or 2" << endl;
    cerr << "<v VCI>   = Virtual Channel Identifier" << endl;
    cerr << "[p PORT]  = Port number (default 0)" << endl;
    cerr << "[d]       = Debug trace (default off)" << endl;
    cerr << endl;
    cerr << "Configuration 1:" << endl;
    cerr << "- calling global title = " << callingGT_1 << endl;
    cerr << "- called global title = " << calledGT_1 << endl;
    cerr << "- orig. point code = " << origPC_1 << endl;
    cerr << "- dest. point code = " << destPC_1 << endl;
    cerr << endl;
    cerr << "Configuration 2:" << endl;
    cerr << "- calling global title = " << callingGT_2 << endl;
    cerr << "- called global title = " << calledGT_2 << endl;
    cerr << "- orig. point code = " << origPC_2 << endl;
    cerr << "- dest. point code = " << destPC_2 << endl;
    cerr << endl;
    exit(0);
}

int main(int argc, char *argv[])
{
    int config = -1;
    int vci = -1;
    int port = 0;

    int count = 1;

    if (argc < 2)
    {
        printUsage(argv[0]);
    }

    while (count < argc)
    {
        switch (*argv[count++])
        {
            case 'c':
              config = atoi(argv[count++]);
	      break;
            case 'v':
              vci = atoi(argv[count++]);
              break;
            case 'p':
              port = atoi(argv[count++]);
              break;
            case 'd':
              debugOutputCout();
	      break;
            case '-':
              count = argc;
              break;
            case 'h':
            default:
              printUsage(argv[0]);
              break;
	}
    }
    if ((config != 1 && config != 2) || vci == -1)
    {
        printUsage(argv[0]);
    }


    string callingGT(callingGT_1);
    string calledGT(calledGT_1);
    string origPC(origPC_1);
    string destPC(destPC_1);

    if (config != 1)
    {
        callingGT = callingGT_2;
        calledGT = calledGT_2;
        origPC = origPC_2;
        destPC = destPC_2;
    }

    pfSystem::init(argc, argv);

    // Initialize variables
    pfId id = 0;
    pfKey maxValue = 1000;
    const pfKey SCCP = 3;

    int OPC = atoi(origPC.c_str());
    int DPC = atoi(destPC.c_str());
    
    // SS7 configure object
    ss7Configure configure = ss7ConfigureImplementation::createSS7Configure();
    configure.setPointCode(OPC);

    if (config == 1)
    {
        configure.addGTtoPC(calledGT, DPC);
        configure.configureRoutingTable(14, 15, 1); // PC 14-15 => AALid 1
    }
    else
    {
        configure.addGTtoPCandSSN(callingGT, DPC, 11);  // 11 = INAP
        configure.configureRoutingTable(10, 12, 1); // PC 10-12 => AALid 1
    }

    configure.printConfigure(cout);

   
    // Create implementations
    pfBoolean ACK = 0;
    tcapAdapter *upAdapter = new tcapAdapter(origPC, ACK);

    saalNNIlink *link = saalNNIlink::createATMNNIlink(id, port, 0, vci);
    link->setN1(1);  // Only one proving-PDUs
    pfConduit nsscfProxy = link->getConduit();

    pfConduit mtp3Proxy(mtp3Protocol::createProtocol(configure));
    pfConduit sccpProxy = sccpProtocol::createProtocol(configure);

    // Create conduit proxies
    pfConduit upAdapterProxy(upAdapter);

    string SI("serviceIndicator");
    pfConduit userMuxProxy = pfMux::createMux(maxValue, SI);
    string AAL("AALid");
    pfConduit aalMuxProxy = pfMux::createMux(maxValue, AAL);

    // Set ids
    upAdapterProxy.setId(id);

    userMuxProxy.setId(id);
    aalMuxProxy.setId(id);    

    mtp3Proxy.setId(id);
    sccpProxy.setId(id);

    // Connect conduits
    aalMuxProxy.connectToA(mtp3Proxy);
    userMuxProxy.connectToA(mtp3Proxy);

    mtp3Proxy.connectToB(userMuxProxy);
    mtp3Proxy.connectToA(aalMuxProxy);

    sccpProxy.connectToB(upAdapterProxy);
    upAdapterProxy.connectToA(sccpProxy);

    // Connect user parts
    configure.setSCCP();

    mtpConfigTransporter configTransp =
        mtpConfigTransporter::createConfigSideB(SCCP, sccpProxy);
    mtp3Proxy.accept(&configTransp);

    // Connect sub systems
    configure.setTCAP();
    configure.setINAP();
    
    // Connect AAL connection(s)
    mtpConfigTransporter configTranspAAL1 =
        mtpConfigTransporter::createConfigSideA(1, nsscfProxy);
    mtp3Proxy.accept(&configTranspAAL1);

    // Set up SAAL connection
    naalSTARTreq *startMessenger = new naalSTARTreq;
    pfMsgTransporter *startMessage = 
        pfMsgTransporter::createMsgTransporter(startMessenger);
    startMessage->setSender(aalMuxProxy);
    nsscfProxy.accept(startMessage);

    try
    {
        pfSystem::instance()->run();
    }
    catch (...)
    {
        debugUser("Exception catched in main");
    }
    return 0;
}
