//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project
//
//File: forwarder.cpp
//
//Version: $Revision: 1.22 $
//
//State: $State: Exp $
//
//Date: $Date: 1999/01/21 13:06:43 $
//
//Organisation:
//	Open Environment Software Oy
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Vesa-Matti Puro
//      Jussi Turunen
//
//Description:
//      See corresponding header file.
//
//Copyright:
//	Copyright Open Environment software Oy (unpublished / work in progress)
//      ALL RIGHTS RESERVED.
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 

#include <typeinfo>
#include "pf/error.h"
#include "forwarder.h"

#include <stdio.h>
#include <stdlib.h>

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

oesSender
     :: oesSender(string identifier_,
                  otMessage::SerializedMessage message_,
                  otMessage_ptr ior_,
                  string destination_)
     : _identifier(identifier_),
       _message(message_),
       _ior(ior_),
       _destination(destination_)
{
    return;
}

oesSender :: ~oesSender(void)
{
    return;
}

void oesSender :: run(void)
{
    const unsigned int DEBUG_BUFFER_SIZE = 80;
    char buffer[DEBUG_BUFFER_SIZE] = "ETS ERROR: oesSender::run";
    string debugOutput;

    debugString("run start", _identifier);
    printMessage(_identifier, _message);
    debugTime();
    _ior->send(_identifier.c_str(), _message);
    (void)sprintf(buffer,
                  "\t%s%s (%ld)",
                  _destination.c_str(),
                  _identifier.c_str(),
                  _message.length());
    debugOutput = buffer;
    debugUser(debugOutput);
    debugUser("run end");
    return;
}

//
// Method:
//
// Description:
//

oesForwarder :: oesForwarder(CORBA_ORB_ptr orb_)
    : otMessage_skel(),
      _init(),
      _n1tior(),
      _n1rior(),
      _iutior(),
      _opior(),
      _testertior(),
      _testerrior()
{
    string n1tiorStr("testerAdaptert.ref");
    string n1riorStr("testerAdapterr.ref");
    string iutiorStr("IUTAdapter.ref");
    string opiorStr("oper.ref");
    string testertiorStr("testert.ref");
    string testerriorStr("testerr.ref");

    _n1tior = otMessage::_narrow(loadIOR(orb_, n1tiorStr));
    _n1rior = otMessage::_narrow(loadIOR(orb_, n1riorStr));
    _iutior = otMessage::_narrow(loadIOR(orb_, iutiorStr));
    _opior = otMessage::_narrow(loadIOR(orb_, opiorStr));
    _testertior = otMessage::_narrow(loadIOR(orb_, testertiorStr));
    _testerrior = otMessage::_narrow(loadIOR(orb_, testerriorStr));

    debugUser("forwarder started");
    return;
}

oesForwarder :: ~oesForwarder(void)
{
    return;
}

void oesForwarder
    :: send(const char* identifier_,
            const otMessage::SerializedMessage& message_)
{
    debugUser("send start");

    if (identifier_ == 0)
    {
        debugUser("ETS ERROR: null identifier");
        throw otMessage::DecodeError();
    }

    string recid = identifier_;
    string identifier = &identifier_[2];
    debugString("received identifier", recid);

    if (identifier == "$OES_START_OF_CASE")
    {
        debugString ("STARTING CASE", message_[0].value.in()); 
        if (identifier_[0] == 'I')
        {
            JTCThread *t2 = new oesSender(identifier, message_,
                                          _iutior, "IUT!");
            t2->start();
        } 
        else if (identifier_[1] == 'L')
        {
            JTCThread *t1 = new oesSender(identifier, message_,
                                          _n1tior, "LN1!");
            t1->start();
            JTCThread *t3 = new oesSender(identifier, message_,
                                          _opior, "OPER!");
            t3->start();
        } 
        else if (identifier_[1] == 'T')
        {
            JTCThread *t1 = new oesSender(identifier, message_,
                                          _n1tior, "TN1!");
            t1->start();
            JTCThread *t3 = new oesSender(identifier, message_,
                                          _opior, "OPER!");
            t3->start();
        } 
        else if (identifier_[1] == 'R')
        {
            JTCThread *t1 = new oesSender(identifier, message_,
                                          _n1rior, "RN1!");
            t1->start();
        } 
        else
        {
            debugUser("ETS_ERROR in check: unknown destination in start");
        } 
    }
    else if (identifier_[0] == 'T')
    {
        JTCThread *t = 0; 
        if (identifier_[1] == 'L')
        {
            t = new oesSender(identifier, message_, _testertior, "LN1?");
            t->start();
        } 
        else if (identifier_[1] == 'T')
        {
            t = new oesSender(identifier, message_, _testertior, "TN1?");
            t->start();
        } 
        else if (identifier_[1] == 'R')
        {
            t = new oesSender(identifier, message_, _testerrior, "RN1?");
            t->start();
        } 
        else
        {
            debugUser("ETS_ERROR in check: unknown destination");
        } 
    }
    else if (identifier_[0] == 'N')
    {
        JTCThread *t = 0; 
        if (identifier_[1] == 'L')
        {
            t = new oesSender(identifier, message_, _n1tior, "LN1!");
            t->start();
        } 
        else if (identifier_[1] == 'T')
        {
            t = new oesSender(identifier, message_, _n1tior, "TN1!");
            t->start();
        } 
        else if (identifier_[1] == 'R')
        {
            t = new oesSender(identifier, message_, _n1rior, "RN1!");
            t->start();
        } 
        else
        {
            debugUser("ETS_ERROR in check: unknown destination");
        } 
    }
    else if (identifier_[0] == 'I')
    {
        JTCThread *t = new oesSender(identifier, message_, _iutior, "IUT!");
        t->start();
    }
    else
    {
        debugUser("ETS_ERROR in check: error in destination");
    }

    debugString("send end", identifier);
    return;
}

otMessage::SerializedMessage *oesForwarder
    :: sendTwoWay(const char *identifier_,
                  const ParameterList& message_)
{
    const unsigned int DEBUG_BUFFER_SIZE = 80;
    char buffer[DEBUG_BUFFER_SIZE] = "ETS ERROR: oesForwarder::sendTwoWay";
    string debugOutput;

    debugUser("sendTwoWay start");

    otMessage::SerializedMessage *result =
        _opior->sendTwoWay(identifier_, message_);

    (void)sprintf(buffer, //DEBUG_BUFFER_SIZE,
                   "%s (%ld)",
                    identifier_,
                    message_.length());

    debugOutput = buffer;
    debugUser(debugOutput);
    debugUser("sendTwoWay end");
    return result; 
}

CORBA_Object_ptr oesForwarder
    :: loadIOR(CORBA_ORB_ptr orb_, const string &filename_)
{
    CORBA_Object_ptr obj = 0;

    try
    {
        FILE *fp = fopen(filename_.c_str(), "r");

        if (fp == 0)
        {
            return 0;
        }

        char s[1000];
        fscanf(fp, "%s", s);
        fclose(fp);

        obj = orb_->string_to_object(s);
        assert(!CORBA_is_nil(obj));
        debugString("oesForwarder: using:", filename_);
    }
    catch(...)
    {
        debugString("oesForwarder: ETS_ERROR: can't open file", filename_);
        return 0;
    }

    return obj;
}

void oesSender :: printMessage(const string &identifier_,
                        const otMessage::SerializedMessage& message_)
{
    debugString("printing message", identifier_);
    for (pfUlong i = 0; i < message_.length(); ++i)
    {
        otMessage::ElementKind kind = message_[i].kind;
        string id = message_[i].identifier.in();
        string value = message_[i].value.in();
        pfUlong number = message_[i].number;
        debugString("id", id);
        debugPfUlong("kind", kind);
        if (kind == otMessage::Integer ||
            kind == otMessage::Boolean)
        {
            debugPfUlong("number", number);
        }
        else
        {
            debugString("value", value);
        }
    }
    return;
}

