//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / sw
//
//File: swilmiimpl.cpp
//
//Version: $Revision: 1.11 $
//
//State: $State: Exp $
//
//Date: $Date: 1999/03/11 16:05:41 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Timo Pärnänen
//
//Description:
//      See corresponding header file.
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 


#include <string>
#include <vector>
#include "pf/debug.h"
#include "pf/system.h"
#include "pf/tools.h"
#include "mgmt/mgmtcommand.h"
#include "swdefs.h"
#include "swswitch.h"
#include "swport.h"
#include "ie/connectionidentifier.h"
#include "swilmiimpl.h"


swIlmiImpl *swIlmiImpl :: createILMI(pfUlong portNumber_, 
                                     pfUlong linkNumber_)
{
    pfUlong pointCode = swSwitch::instance()->getPointCode();

    string pointCodeStr = pfTools::intToString(pointCode);
    string portNumberStr = pfTools::intToString(portNumber_);
    string linkNumberStr = pfTools::intToString(linkNumber_);

    // Create linkIdentifier
    pfUlong linkIdentifier = 
        swSwitch::buildLinkIdentifier(portNumber_, linkNumber_);
        
    pfUlong vpi = swSwitch::instance()->reserveIlmiVPI(linkIdentifier);
    pfUlong vci = swSwitch::instance()->reserveIlmiVCI(linkIdentifier);
    
    string vpiStr = pfTools::intToString(vpi);
    string vciStr = pfTools::intToString(vci);

    swIlmiImpl *ilmi = new swIlmiImpl(linkIdentifier,
                                      pointCodeStr,
                                      portNumberStr,
                                      linkNumberStr,
                                      vpiStr,
                                      vciStr);
    return ilmi;
}

swIlmiImpl :: swIlmiImpl(pfUlong linkIdentifier_,
                         const string &pointCode_, 
                         const string &portNumber_,
                         const string &linkNumber_,
                         const string &vpi_,
                         const string &vci_)
    : mgmtDelegationBase(),
      _vpi(vpi_),
      _vci(vci_),
      _linkIdentifier(linkIdentifier_)
{
    createOB();

    // Construct name for naming component
    string name = pointCode_;
    name += "/ports/";
    name += portNumber_;
    name += "/links/";
    name += linkNumber_;
    name += "/ilmi";

    debugUser(name);
    
    // Register ILMI server to an agent
    try
    {
        
        registerToOther(name);
    }
    catch (...)
    {
        debugUser("registerToOther failed");
    }
    return;
}

swIlmiImpl :: ~swIlmiImpl(void)
{
    // ++TODO++
    // unRegisterFromOther();
    return;
}

void swIlmiImpl :: makeFabricConnection(void)
{
    pfUlong vpi = atoi(_vpi.c_str());
    pfUlong vci = atoi(_vci.c_str());
    pfUlong portNumber = 
        swSwitch::instance()->parsePortNumber(_linkIdentifier);

    ieConnectionIdentifier input;

    input.setPort(portNumber);
    input.setVPCI(SW_ILMI_VPI);
    input.setVCI(SW_ILMI_VCI);
    
    ieConnectionIdentifier output;
    
    output.setPort(SW_FABRIC_CONTROL_PORT);
    output.setVPCI(vpi);
    output.setVCI(vci);
    
    swSwitch::instance()->connect(&input, &output, true, this);
    return;
}

//
//Functions: success/failure
//        
//Description:
//    Implements fabric callback interface

void swIlmiImpl :: success(pfUlong identifier_)
{
    debugUser("success at ILMI --> start");
    sendStart();
    return;
}

void swIlmiImpl :: failure(pfUlong identifier_, pfUlong cause_)
{
    // ++TODO++ error handling

    debugPfUlong("failure at ILMI with cause", cause_);
    return;
}

//
//Functions: mgmtDelegationBase methods
//        
//Description:
//    Inputs from ILMI agent.

string swIlmiImpl :: receiveGet(const string &name_)
{
    // ++TODO++
    debugString("receiveGet", name_);
    string result = "result";
    return result;
}

void swIlmiImpl :: receiveSet(const string &name_, const string &value_)
{
    // ++TODO++
    debugString("receiveSet", name_);
    debugString("value", value_);
    return;
}

void swIlmiImpl :: receiveExecute(mgmtCommand &command_)
{
    command_.setCurrentTheFirst();
    string commandName = command_.getCommandName();
    
    //++TODO++
    // ERROR HANDLING !!!
    // not found, not enough parameter etc..
    
    if (commandName.compare("listAddresses") == 0)
    {
        debugUser("listAddresses");
        for (pfUlong i=0; i<command_.getCommandLength(); i++)
        {
            string address;
            command_.getNextParameter(address);

            // Register addresses to a routing server.
            swSwitch::instance()->setAddress(_linkIdentifier, address);
        }
    }
    else if (commandName.compare("return") == 0)
    {
        debugUser("return");
        // ++TODO++
    }
    else if (commandName.compare("error") == 0)
    {
        debugUser("error");
        for (pfUlong i=0; i < command_.getCommandLength(); i++)
        {
            string name;
            string value;
            string type;
            command_.getNextParameter(name, value, type);
            debugString("name", name);
            debugString("value", value);
            if (i == 0)
            {
                int code = atoi(value.c_str());
                switch (code)
                {
                    case 1 :
                        debugUser("tooBig");
                        break;
                    case 2 :
                        debugUser("noSuchName");
                        break;
                    case 3 :
                        debugUser("badValue");
                        break;
                    case 4 :
                        debugUser("readOnly");
                        break;
                    case 5 :
                        debugUser("genErr");
                        break;
                    default :
                        debugUser("unknown error code");
                        break;
                }
            }
            debugString("type", type);
        }
    }
    else
    {
        debugUser("Invalid command");
    } 
    
    return;
}

// 
//Functions: Send methods
//
//Description:
//    Methods to send commands to an ILMI agent
//
void swIlmiImpl :: sendStart(void)
{
    mgmtCommand command("start");
    command.addParameter("vpi", _vpi);
    command.addParameter("vci", _vci);
    try
    {
        sendExecute(command);
    }
    catch (...)
    {
        // ++TODO++
        debugUser("start failed");
    }    
    return;
}

void swIlmiImpl :: sendStop(void)
{
    mgmtCommand command("stop");
    try
    {
        sendExecute(command);
        debugUser("ILMI stopped");
    }
    catch (...)
    {
        // ++TODO++
        debugUser("start failed");
    }
    return;
}

void swIlmiImpl :: sendListPrefixes(const string &prefix_)
{
    mgmtCommand command("listPrefixes");
    command.addParameter("prefix", prefix_);
    try
    {
        sendExecute(command);
        debugUser("ILMI prefixes listed to agent");
    }
    catch (...)
    {
        // ++TODO++
        debugUser("listprefixes failed");
    }
    return;
}
