//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project
//
//File: 
//
//State: $State: Exp $
//
//Version: $Revision: 1.17 $
//
//Date: $Date: 1998/12/10 10:26:59 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
// 
//Author:
//	Vesa-Matti Puro
//      Harri Sunila
//
//Description:
//      See the corresponding header file.  
//
//Copyright:    
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//      
//Licence:
//     
//
//History:
//
//

#include "gsmpconnectionmanagement.h"
#include "gsmpconnectionmanagementmessages.h"
#include "iface/swif/swfabriccallback.h"
#include "gsmpprotocol.h"

//
// Function: gsmpConnectionManagement
//
// Description:  
//

gsmpConnectionManagement :: gsmpConnectionManagement(void)
    : pfAdapter(),
      gsmpState(),
      _callback(0)
{
    incRefCount();
    return;
}

//
// Function: gsmpConnectionManagement
//
// Description:  
//

gsmpConnectionManagement :: gsmpConnectionManagement(
    swFabricCallback *callback_)
    : pfAdapter(),
      gsmpState(),
      _callback(callback_)
{
    incRefCount();
    return;
}

//
// Function: gsmpConnectionManagement
//
// Description:  
//

gsmpConnectionManagement :: gsmpConnectionManagement(
    const gsmpConnectionManagement &other_)
    : pfAdapter(other_),
      gsmpState(),
      _callback(other_._callback)
{
    return;
}

//
// Function: ~gsmpConnectionManagement
//
// Description:  
//

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

//
// Function: addBranch
//
// Description:
//     Add an output branch for the connection. A successive addBranch
//     adds the specified output branch with a priority specified by
//     the priority_ parameter.
//

pfUlong gsmpConnectionManagement :: addBranch(pfUlong inputPort_,
                                              pfUlong inputVPI_,
                                              pfUlong inputVCI_,
                                              pfUlong outputPort_,
                                              pfUlong outputVPI_,
                                              pfUlong outputVCI_,
                                              pfByte priority_)
{
    pfUlong transactionIdentifier = gsmpProtocol::generateTransactionIdentifier();
    gsmpAddBranchMessage *message = new gsmpAddBranchMessage(
        gsmpMessage::GSMP_ACK_ALL,
        transactionIdentifier, 
        0,
        inputPort_,
        inputVPI_,
        inputVCI_,
        outputPort_,
        outputVPI_,
        outputVCI_,
        priority_);

    sendRequest(message);
    return transactionIdentifier;
}

//
// Function: deleteBranch
//
// Description:
//     Delete an existing branch.
//

pfUlong gsmpConnectionManagement :: deleteBranch(pfUlong inputPort_,
                                                 pfUlong inputVPI_,
                                                 pfUlong inputVCI_,
                                                 pfUlong outputPort_,
                                                 pfUlong outputVPI_,
                                                 pfUlong outputVCI_)
{
    pfUlong transactionIdentifier = gsmpProtocol::generateTransactionIdentifier();
    gsmpDeleteBranchMessage *message = new gsmpDeleteBranchMessage(
        gsmpMessage::GSMP_ACK_ALL,
        transactionIdentifier,
        0,
        inputPort_,
        inputVPI_,
        inputVCI_,
        outputPort_,
        outputVPI_,
        outputVCI_);

    sendRequest(message);
    return transactionIdentifier;
}

//
// Function: deleteTree
//
// Description:
//     Delete the whole tree of output branches. After a successive
//     deleteTree there is no output branches for the specified connection.    
//

pfUlong gsmpConnectionManagement :: deleteTree(pfUlong inputPort_,
                                               pfUlong inputVPI_,
                                               pfUlong inputVCI_)
{
    pfUlong transactionIdentifier = gsmpProtocol::generateTransactionIdentifier();
    gsmpDeleteTreeMessage *message = new gsmpDeleteTreeMessage(
        gsmpMessage::GSMP_ACK_ALL,
        transactionIdentifier,
        0,
        inputPort_,
        inputVPI_,
        inputVCI_);

    sendRequest(message);
    return transactionIdentifier;
}

//
// Function: verifyTree 
//
// Description:
//     Verify that the supposed tree of output branches exist.
//

pfUlong gsmpConnectionManagement :: verifyTree(pfUlong inputPort_,
                                               pfUlong inputVPI_,
                                               pfUlong inputVCI_,
                                               pfUlong numberOfBranches_)
{
    pfUlong transactionIdentifier = gsmpProtocol::generateTransactionIdentifier();
    gsmpVerifyTreeMessage *message = new gsmpVerifyTreeMessage(
        gsmpMessage::GSMP_ACK_ALL,
        transactionIdentifier,
        0,
        inputPort_,
        inputVPI_,
        inputVCI_,
        numberOfBranches_);

    sendRequest(message);
    return transactionIdentifier;
}

//
// Function: deleteAll
//
// Description:
//     Delete all connections in the input port. A successive deleteAll
//     causes that not even the input branch exists anymore.
//

pfUlong gsmpConnectionManagement :: deleteAll(pfUlong inputPort_)
{
    pfUlong transactionIdentifier = gsmpProtocol::generateTransactionIdentifier();
    gsmpDeleteAllMessage *message = new gsmpDeleteAllMessage(
        gsmpMessage::GSMP_ACK_ALL,
        transactionIdentifier,
        0,
        inputPort_);

    sendRequest(message);
    return transactionIdentifier;
}

//
// Function: moveBranch
//
// Description:
//     Move the output branch of the connection from the old to a new one.
//

pfUlong gsmpConnectionManagement :: moveBranch(pfUlong inputPort_,
                                               pfUlong inputVPI_,
                                               pfUlong inputVCI_,
                                               pfUlong oldOutputPort_,
                                               pfUlong oldOutputVPI_,
                                               pfUlong oldOutputVCI_,
                                               pfUlong newOutputPort_,
                                               pfUlong newOutputVPI_,
                                               pfUlong newOutputVCI_,
                                               pfByte priority_)
{
    pfUlong transactionIdentifier = gsmpProtocol::generateTransactionIdentifier();
    gsmpMoveBranchMessage *message = new gsmpMoveBranchMessage(
        gsmpMessage::GSMP_ACK_ALL,
        transactionIdentifier,
        0,
        inputPort_,
        inputVPI_,
        inputVCI_,
        oldOutputPort_,
        oldOutputVPI_,
        oldOutputVCI_,
        newOutputPort_,
        newOutputVPI_,
        newOutputVCI_,
        priority_);

    sendRequest(message);
    return transactionIdentifier;
}

//
// Functions: XXAct
//
// Description:  
//

void gsmpConnectionManagement :: gsmpAddBranchMessageAct(
    gsmpAddBranchMessage *message_,
    pfProtocol *protocol_)
{
    processResponse(message_);
    return;
}

void gsmpConnectionManagement :: gsmpDeleteBranchMessageAct(
    gsmpDeleteBranchMessage *message_,
    pfProtocol *protocol_)
{
    processResponse(message_);
    return;
}

void gsmpConnectionManagement :: gsmpDeleteTreeMessageAct(
    gsmpDeleteTreeMessage *message_,
    pfProtocol *protocol_)
{
    processResponse(message_);
    return;
}

void gsmpConnectionManagement :: gsmpVerifyTreeMessageAct(
    gsmpVerifyTreeMessage *message_,
    pfProtocol *protocol_)
{
    processResponse(message_);
    return;
}

void gsmpConnectionManagement :: gsmpDeleteAllMessageAct(
    gsmpDeleteAllMessage *message_,
    pfProtocol *protocol_)
{
    processResponse(message_);
    return;
}

void gsmpConnectionManagement :: gsmpMoveBranchMessageAct(
    gsmpMoveBranchMessage *message_,
    pfProtocol *protocol_)
{
    processResponse(message_);
    return;
}

//
// Function: sendRequest
//
// Description:  
//

void gsmpConnectionManagement :: sendRequest(
    gsmpConnectionManagementMessage *message_)
{
    pfConduit sender(this);
    pfMsgTransporter *transporter = pfMsgTransporter::createMsgTransporter(
        message_);
    transporter->setSender(sender);
    toA(transporter);
    return;
}

//
// Function: processResponse
//
// Description:
//     Call either success() or failure() of swFabricCallback.
//

void gsmpConnectionManagement :: processResponse(
    gsmpConnectionManagementMessage *message_)
{
    pfUlong transactionIdentifier = message_->getTransactionIdentifier();
    pfByte result = message_->getResult();

    if (_callback != 0)
    {
        if (result == gsmpMessage::GSMP_SUCCESS)
        {
            _callback->success(transactionIdentifier);
        }
        else
        {
            pfByte code = message_->getCode();
            _callback->failure(transactionIdentifier,
                               code);
        }
    }
    return;
}
