/*
 * Copyright 2019-present Infosys Limited  
 *   
 * SPDX-License-Identifier: Apache-2.0    
 */
 
/******************************************************************************
 *
 * This is an auto generated file.
 * Please do not edit this file.
 * All edits to be made through template source file
 * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/stacktemplate.cpp.tt>
 ******************************************************************************/
#include <cstring>
#include <stdint.h>
#include "gtpV2Stack.h"
#include "msgClasses/gtpV2MsgFactory.h"
#include "msgClasses/manual/gtpV2Message.h"
[% FOREACH msg IN tempdata.msgList -%]
#include "msgClasses/[% msg.msgFileName %].h"
[% END -%]

cmn::utils::Debug errorStream;

GtpV2Stack::GtpV2Stack ()
{
    // TODO Auto-generated constructor stub

}

GtpV2Stack::~GtpV2Stack ()
{
    // TODO Auto-generated destructor stub
}

bool
GtpV2Stack::encodeMessage (GtpV2MessageHeader & msgHeader, 
			   MsgBuffer & buffer, void *data_p)
{

    //Clear the global errorStream
    errorStream.clearStream ();
    bool rc = false;
    GtpV2Message & msg =
    GtpV2MsgFactory::getInstance ().getMsgObject (msgHeader.msgType);

	uint16_t gtpHeaderStartIdx = buffer.getCurrentIndex();
    // Encode the header
    GtpV2Message::encodeHeader (buffer, msgHeader);

    Uint16 startIndex = buffer.getCurrentIndex();

    switch (msgHeader.msgType)
    {
[% FOREACH msg IN tempdata.msgList -%]
        case [% msg.className %]Type:
        {
            if (data_p != NULL)
            {
                rc =
               dynamic_cast<
               [% msg.className %] & >(msg).
               encode[% msg.className %](buffer,
    			     *(([% msg.className %]Data *)
        			     data_p));
            }
            else
            { 
                // Application has filled the data structure provided by the stack
                rc = 
                dynamic_cast<
                [% msg.className %] & >(msg).
                encode[% msg.className %] (buffer,
                            [% msg.dataMember %]);
            }
            break;
        }
[% END -%]
    }

    Uint16 endIndex = buffer.getCurrentIndex ();

    Uint16 messageLength = (endIndex - startIndex)+8;

    buffer.goToIndex (gtpHeaderStartIdx  + 2); // 2 is where length is encoded in a gtp message TODO remove hardcoding
    buffer.writeUint16 (messageLength, false);
    buffer.goToIndex (endIndex);
    return rc;
}

bool
GtpV2Stack::decodeGtpMessageHeader(GtpV2MessageHeader& msgHeader, MsgBuffer& buffer)
{
	 return GtpV2Message::decodeHeader (buffer, msgHeader);
}


bool
GtpV2Stack::decodeMessage (GtpV2MessageHeader& msgHeader, 
                MsgBuffer& buffer,void* data_p)
{
    errorStream.clearStream();
    // First decode the message header
    bool rc = false;
      
    
    
    Uint16 msgDataLength = msgHeader.msgLength;
    
    if (msgHeader.teidPresent)
    {
        msgDataLength = msgDataLength - 8; //teid and sequence number
    }
    else
    {
        msgDataLength = msgDataLength - 4; //only sequence number
    }
  
    // Validate the length before proceeding
    if (msgDataLength != buffer.lengthLeft() )
    {
        // Encoded message length does not match the number of bytes left in the message
        errorStream.add ((char *)"Message length does not match bytes in buffer\n");
        errorStream.add ((char *)"Computed Message length: ");
        errorStream.add (msgDataLength);
        errorStream.add ((char *)"  Bytes Left in buffer: ");
        errorStream.add (buffer.lengthLeft());
        errorStream.endOfLine ();
        return false;
    }

    GtpV2Message& msg = 
    GtpV2MsgFactory::getInstance ().getMsgObject (msgHeader.msgType);

    switch (msgHeader.msgType){
[% FOREACH msg IN tempdata.msgList -%]
        case [% msg.className %]Type:
        {
            if (data_p != NULL)
            {
                rc =
                dynamic_cast<
                [% msg.className %] & >(msg).
                decode[% msg.className %](buffer,
                            *([% msg.className %]Data*)
                             data_p, msgDataLength);
            }
            else
            { 
                // Application wants to use the data structure provided by the stack
                // let us first clear any data present in the internal data structure
                memset (&[% msg.dataMember %], 0,
                sizeof ([% msg.className %]Data));
                rc =
                dynamic_cast<
                [% msg.className %] & >(msg).
                decode[% msg.className %](buffer,
                            [% msg.dataMember %],
                            msgDataLength);
            }
            break;
        }
[% END -%]
    }
    return rc;
}

void 
GtpV2Stack::display_v(Uint8 msgType, Debug& stream, void* data_p)
{
    // Display the messageType
    stream.add ((char *)"MessageType: ");
    stream.add (msgType);
    stream.endOfLine ();
      
    GtpV2Message& msg = GtpV2MsgFactory::getInstance ().getMsgObject (msgType);

    switch (msgType){
[% FOREACH msg IN tempdata.msgList -%]
        case [% msg.className %]Type:
        {
            stream.add ((char *)"Message: [% msg.className %]");
            stream.endOfLine ();
            if (data_p != NULL)
            {
            dynamic_cast<
            [% msg.className %] & >(msg).
            display[% msg.className %]Data_v (*
                        (([% msg.className %]Data*) data_p), stream);
            }
            else
            {
            // Application wants to use the data structure provided by the stack
            dynamic_cast<
            [% msg.className %] & >(msg).
            display[% msg.className %]Data_v
                        ([% msg.dataMember %], stream);
            }
           break;
        }
[% END -%]
    }
}
