//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / gsmpswitch
//
//File: gsmpswitchactivestate.cpp
//
//Version: $Revision: 1.1 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/08/03 11:40:42 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Sami Raatikainen
//
//Description:
//      See the corresponding header file.
//
//Copyright:
//
//
//Licence:
//
//
//History: 

#include "gsmpswitchprotocol.h"
#include "gsmpswitchactivestate.h"
#include "protocol/gsmp/gsmpconnectionmanagementmessages.h"
#include "protocol/gsmp/gsmpportmanagementmessages.h"
#include "protocol/gsmp/gsmpconfigurationmessages.h"
#include "protocol/gsmp/gsmpstatisticsmessages.h"
//#include "gsmptimeouts.h"


gsmpSwitchActiveState *gsmpSwitchActiveState::_only = 0;

gsmpSwitchActiveState :: gsmpSwitchActiveState(void)
{
    return;
}

gsmpSwitchActiveState :: ~gsmpSwitchActiveState(void)
{
    _only = 0;
    return;
}

gsmpSwitchActiveState *gsmpSwitchActiveState :: instance(void)
    throw (pfMemoryAllocationException)
{
    if (_only == 0)
    {
        _only = new gsmpSwitchActiveState;
    }
    if (_only == 0)
    {
        throw pfMemoryAllocationException(PF_EX_INFO,
                                          sizeof(gsmpSwitchActiveState));
    }
    return _only;
}


//
// Function: gsmpAddBranchMessageAct  uses dynamic_cast
//
// Description:  
//

void gsmpSwitchActiveState :: gsmpAddBranchMessageAct(
    gsmpAddBranchMessage *message_,
    pfProtocol *protocol_)
{
    cout << "gsmpSwitchActiveState: gsmpAddBranchMessageAct" << endl;

    gsmpSwitchProtocol *protocol =
        dynamic_cast<gsmpSwitchProtocol *>(protocol_);
    gsmpAddBranchMessage *message;
    try
    {
        message = message_->clone();
    }
    catch (pfException &exception)
    {
        exception.printInfo();
        throw;
    }
    pfByte result = (pfByte)(message->getInteger("_result"));
//    pfByte code = (pfByte)(message->getInteger("_code"));
    pfUlong inputPort = message->getInteger("_inputPort");
    pfUlong portSessionNumber = message->getInteger("_portSessionNumber");
    pfUlong switchPortSessionNumber =
        protocol->getPortSessionNumber(inputPort);    
    switch (result)
    {
        case gsmpMessage::GSMP_NO_SUCCESS_ACK:     // Request
            if (portSessionNumber == switchPortSessionNumber)
            {
                if (protocol->addBranch(message) == 0)
                {
                    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                    message->setInteger("_code",
                                        gsmpMessage::GSMP_E_MSG_SPECIFIC);
                    protocol->toA(message);
                }
            }
            else
            {
                message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                message->setInteger("_code",
                                    gsmpMessage::GSMP_E_INVAL_PORT_SESS);
                protocol->toA(message);
            }
            break;
            
        case gsmpMessage::GSMP_ACK_ALL:        // Request
            if (portSessionNumber == switchPortSessionNumber)
            {
                if (protocol->addBranch(message) == 0)
                {
                    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                    message->setInteger("_code",
                                        gsmpMessage::GSMP_E_MSG_SPECIFIC);
                }
                else
                {
                    message->setInteger("_result", gsmpMessage::GSMP_SUCCESS);
                    message->setInteger("_code", gsmpMessage::GSMP_E_SUCCESS);
                }
            }
            else
            {
                message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                message->setInteger("_code",
                                    gsmpMessage::GSMP_E_INVAL_PORT_SESS);
            }
            protocol->toA(message);
            break;
            
        case gsmpMessage::GSMP_SUCCESS:        // Response, ignore
            break;
            
        case gsmpMessage::GSMP_FAILURE:        // Response, ignore
            break;
    }
    return;
}


//
// Function: gsmpDeleteBranchMessageAct
//
// Description:  
//

void gsmpSwitchActiveState :: gsmpDeleteBranchMessageAct(
    gsmpDeleteBranchMessage *message_,
    pfProtocol *protocol_)
{
    cout << "gsmpSwitchActiveState: gsmpDeleteBranchMessageAct" << endl;
    
    gsmpSwitchProtocol *protocol =
        dynamic_cast<gsmpSwitchProtocol *>(protocol_);
    gsmpDeleteBranchMessage *message;
    try
    {
        message = message_->clone();
    }
    catch (pfException &exception)
    {
        exception.printInfo();
        throw;
    }
    pfByte result = (pfByte)(message->getInteger("_result"));
//    pfByte code = (pfByte)(message->getInteger("_code"));
    pfUlong inputPort = message->getInteger("_inputPort");
    pfUlong portSessionNumber = message->getInteger("_portSessionNumber");
    pfUlong switchPortSessionNumber =
        protocol->getPortSessionNumber(inputPort);
    switch (result)
    {
        case gsmpMessage::GSMP_NO_SUCCESS_ACK:     // Request
            if (portSessionNumber == switchPortSessionNumber)
            {
                if (protocol->deleteBranch(message) == 0)
                {
                    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                    message->setInteger("_code",
                                        gsmpMessage::GSMP_E_MSG_SPECIFIC);
                    protocol->toA(message);
                }
            }
            else
            {
                message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                message->setInteger("_code",
                                    gsmpMessage::GSMP_E_INVAL_PORT_SESS);
                protocol->toA(message);
            }
            break;
            
        case gsmpMessage::GSMP_ACK_ALL:        // Request
            if (portSessionNumber == switchPortSessionNumber)
            {
                if (protocol->deleteBranch(message) == 0)
                {
                    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                    message->setInteger("_code",
                                        gsmpMessage::GSMP_E_MSG_SPECIFIC);
                }
                else
                {
                    message->setInteger("_result", gsmpMessage::GSMP_SUCCESS);
                    message->setInteger("_code", gsmpMessage::GSMP_E_SUCCESS);
                }
            }
            else
            {
                message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                message->setInteger("_code",
                                    gsmpMessage::GSMP_E_INVAL_PORT_SESS);
            }
            protocol->toA(message);
            break;
            
        case gsmpMessage::GSMP_SUCCESS:        // Response, ignore
            break;
            
        case gsmpMessage::GSMP_FAILURE:        // Response, ignore
            break;
    }
    return;
}

//
// Function: gsmpDeleteTreeMessageAct
//
// Description:  
//
    
void gsmpSwitchActiveState :: gsmpDeleteTreeMessageAct(
    gsmpDeleteTreeMessage *message_,
    pfProtocol *protocol_) throw (pfNullPointerException)
{
    gsmpSwitchProtocol *protocol = dynamic_cast<gsmpSwitchProtocol *>(protocol_);
    gsmpDeleteTreeMessage *message;
    try
    {
        message = message_->clone();
    }
    catch (pfException &exception)
    {
        exception.printInfo();
        throw;
    }

    // set result to GSMP_FAILURE
    // set code to GSMP_E_NOT_IMPL
    // send message back
    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
    message->setInteger("_code", gsmpMessage::GSMP_E_NOT_IMPL);
    protocol->toA(message);
    return;
}

//
// Function: gsmpVerifyTreeMessageAct
//
// Description:  
//

void gsmpSwitchActiveState :: gsmpVerifyTreeMessageAct(
    gsmpVerifyTreeMessage *message_,
    pfProtocol *protocol_) throw (pfNullPointerException)
{
    gsmpSwitchProtocol *protocol = dynamic_cast<gsmpSwitchProtocol *>(protocol_);
    gsmpVerifyTreeMessage *message;
    try
    {
        message = message_->clone();
    }
    catch (pfException &exception)
    {
        exception.printInfo();
        throw;
    }

    // set result to GSMP_FAILURE
    // set code to GSMP_E_NOT_IMPL
    // send message back
    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
    message->setInteger("_code", gsmpMessage::GSMP_E_NOT_IMPL);
    protocol->toA(message);
    return;
}

//
// Function: gsmpDeleteAllMessageAct
//
// Description:  
//

void gsmpSwitchActiveState :: gsmpDeleteAllMessageAct(
    gsmpDeleteAllMessage *message_,
    pfProtocol *protocol_) throw (pfNullPointerException)
{
    cout << "gsmpSwitchActiveState: gsmpDeleteAllMessageAct" << endl;
    
    gsmpSwitchProtocol *protocol =
        dynamic_cast<gsmpSwitchProtocol *>(protocol_);
    gsmpDeleteAllMessage *message;
    try
    {
        message = message_->clone();
    }
    catch (pfException &exception)
    {
        exception.printInfo();
        throw;
    }
    
    // set result to GSMP_FAILURE
    // set code to GSMP_E_NOT_IMPL
    // send message back
    //    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
    //    message->setInteger("_code", gsmpMessage::GSMP_E_NOT_IMPL);
    //    protocol->toA(message);
    
    pfByte result = (pfByte)(message->getInteger("_result"));
    pfUlong inputPort = message->getInteger("_inputPort");
    pfUlong portSessionNumber = message->getInteger("_portSessionNumber");
    pfUlong switchPortSessionNumber =
        protocol->getPortSessionNumber(inputPort);
    switch (result)
    {
        case gsmpMessage::GSMP_NO_SUCCESS_ACK:     // Request
            if (portSessionNumber == switchPortSessionNumber)
            {
                if (protocol->deleteAll(inputPort) == 0)
                {
                    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                    message->setInteger("_code",
                                        gsmpMessage::GSMP_E_MSG_SPECIFIC);
                    protocol->toA(message);
                }
            }
            else
            {
                message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                message->setInteger("_code",
                                    gsmpMessage::GSMP_E_INVAL_PORT_SESS);
                protocol->toA(message);
            }
            break;
            
        case gsmpMessage::GSMP_ACK_ALL:        // Request
            if (portSessionNumber == switchPortSessionNumber)
            {
                if (protocol->deleteAll(inputPort) == 0)
                {
                    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                    message->setInteger("_code",
                                        gsmpMessage::GSMP_E_MSG_SPECIFIC);
                }
                else
                {
                    message->setInteger("_result", gsmpMessage::GSMP_SUCCESS);
                    message->setInteger("_code", gsmpMessage::GSMP_E_SUCCESS);
                }
            }
            else
            {
                message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
                message->setInteger("_code",
                                    gsmpMessage::GSMP_E_INVAL_PORT_SESS);
            }
            protocol->toA(message);
            break;
            
        case gsmpMessage::GSMP_SUCCESS:        // Response, ignore
            break;
            
        case gsmpMessage::GSMP_FAILURE:        // Response, ignore
            break;
    }
    
    return;
}

//
// Function: gsmpMoveBranchMessageAct
//
// Description:  
//

void gsmpSwitchActiveState :: gsmpMoveBranchMessageAct(
    gsmpMoveBranchMessage *message_,
    pfProtocol *protocol_) throw (pfNullPointerException)
{
    gsmpSwitchProtocol *protocol = dynamic_cast<gsmpSwitchProtocol *>(protocol_);
    gsmpMoveBranchMessage *message;
    try
    {
        message = message_->clone();
    }
    catch (pfException &exception)
    {
        exception.printInfo();
        throw;
    }

    // set result to GSMP_FAILURE
    // set code to GSMP_E_NOT_IMPL
    // send message back
    message->setInteger("_result", gsmpMessage::GSMP_FAILURE);
    message->setInteger("_code", gsmpMessage::GSMP_E_NOT_IMPL);
    protocol->toA(message);
    return;
}


//
// Function: gsmpSwitchConfigurationRequestMessageAct
//
// Description:  to do failure response, types
//

void gsmpSwitchActiveState :: gsmpSwitchConfigurationRequestMessageAct(
    gsmpSwitchConfigurationRequestMessage *message_,
    pfProtocol *protocol_) throw (pfNullPointerException)
{
    cout << "gsmpSwitchActiveState:gsmpSwitchConfigurationRequestMessageAct"
         << endl;
    gsmpSwitchProtocol *protocol =
        dynamic_cast<gsmpSwitchProtocol *>(protocol_);
    if (message_ == 0)
    {
        throw pfNullPointerException(PF_EX_INFO);
    }
    else
    {
        pfUlong transactionIdentifier = message_->getInteger(
            "_transactionIdentifier");        
        gsmpSwitchConfigurationResponseMessage *message =
            new gsmpSwitchConfigurationResponseMessage(
                transactionIdentifier,
                0,   // pfUlong firmwareVersionNumber
                0,   // pfUlong switchType
                0);  // string switchName
        
        if (message == 0)
        {
            throw pfMemoryAllocationException(
                PF_EX_INFO,
                sizeof(gsmpPortConfigurationResponseMessage));
        }
        else
        {
            protocol->toA(message);
        }
        
    }
    return;
}

//
// Function: gsmpPortConfigurationRequestMessageAct
//
// Description:   to do failure response
//

void gsmpSwitchActiveState :: gsmpPortConfigurationRequestMessageAct(
    gsmpPortConfigurationRequestMessage *message_,
    pfProtocol *protocol_)
{
    cout << "gsmpSwitchActiveState: gsmpPortConfigurationRequestMessageAct"
         << endl; 
    gsmpSwitchProtocol *protocol =
        dynamic_cast<gsmpSwitchProtocol *>(protocol_);
    pfUlong transactionIdentifier =
        message_->getInteger("_transactionIdentifier");
    pfUlong port = message_->getInteger("_port");
    
    if (protocol->portExists(port) != 0)
    {
        pfUlong minVPI = protocol->getMinVPI(port);
        pfUlong maxVPI = protocol->getMaxVPI(port);
        pfUlong minVCI = protocol->getMinVCI(port);
        pfUlong maxVCI = protocol->getMaxVCI(port);
        pfUlong cellRate = protocol->getCellRate(port);
        pfByte portStatus = protocol->getPortStatus(port);
        pfByte portType = protocol->getPortType(port);
        pfByte lineStatus = protocol->getLineStatus(port);
        pfByte priorities = protocol->getPriorities(port);
        pfUlong portSessionNumber = protocol->getPortSessionNumber(port);
        
        gsmpPortConfigurationResponseMessage *message =
            new gsmpPortConfigurationResponseMessage(transactionIdentifier,
                                                     port,
                                                     portSessionNumber,
                                                     minVPI,
                                                     maxVPI,
                                                     minVCI,
                                                     maxVCI,
                                                     cellRate,
                                                     portStatus,
                                                     portType,
                                                     lineStatus,
                                                     priorities);
        if (message == 0)
        {
            throw pfMemoryAllocationException(
                PF_EX_INFO,
                sizeof(gsmpPortConfigurationResponseMessage));
        }
        else
        {
            protocol->toA(message);
        }
    }
    return;
}

//
// Function: gsmpAllPortsConfigurationRequestMessageAct
//
// Description:   to do failure response
//

void gsmpSwitchActiveState :: gsmpAllPortsConfigurationRequestMessageAct(
    gsmpAllPortsConfigurationRequestMessage *message_,
    pfProtocol *protocol_)
{
    cout << "gsmpSwitchActiveState: gsmpAllPortsConfigurationRequestMessageAct"
         << endl;
    gsmpSwitchProtocol *protocol =
        dynamic_cast<gsmpSwitchProtocol *>(protocol_);
    if (message_ == 0)
    {
        throw pfNullPointerException(PF_EX_INFO);
    }
    else
    {
        pfUlong transactionIdentifier = message_->getInteger(
            "_transactionIdentifier");
// ++TODO++ the third parameter was added without knowledge of the parameter
        gsmpAllPortsConfigurationResponseMessage *message =
            new gsmpAllPortsConfigurationResponseMessage(transactionIdentifier,
                                                         0, 0);
        if (message == 0)
        {
            throw pfMemoryAllocationException(
                PF_EX_INFO,
                sizeof(gsmpAllPortsConfigurationResponseMessage));
        }
        else
        {
            message->setInteger("_portRecordLength",
                                gsmpMessage::PORT_RECORD_LENGTH);
            message->setInteger("_result", gsmpMessage::GSMP_SUCCESS);
            message->setInteger("_code", 0);
            pfUlong port = 1;
            pfUlong minVPI;
            pfUlong maxVPI;
            pfUlong minVCI;
            pfUlong maxVCI;
            pfUlong cellRate;
            pfByte portStatus;
            pfByte portType;
            pfByte lineStatus;
            pfByte priorities;
            pfUlong portSessionNumber;

            // Get the configuration of all ports
            while (protocol->portExists(port) != 0)
            {
                minVPI = protocol->getMinVPI(port);
                maxVPI = protocol->getMaxVPI(port);
                minVCI = protocol->getMinVCI(port);
                maxVCI = protocol->getMinVCI(port);
                cellRate = protocol->getCellRate(port);
                portStatus = protocol->getPortStatus(port);
                portType = protocol->getPortType(port);
                lineStatus = protocol->getLineStatus(port);
                priorities = protocol->getPriorities(port);
                portSessionNumber = protocol->getPortSessionNumber(port);
                message->addPortRecord(port,
                                       portSessionNumber,
                                       minVPI,
                                       maxVPI,
                                       minVCI,
                                       maxVCI,
                                       cellRate,
                                       portStatus,
                                       portType,
                                       lineStatus,
                                       priorities);
                port++;
            }
        }
        protocol->toA(message);
    }      
    return;
}







