//******************************************************************************
//
// Restricted Rights
// WARNING: This is a restricted distribution Zeligsoft file.
//
//******************************************************************************
//
// Copyright (C) 2006 Zeligsoft Inc. - All Rights Reserved
//

//******************************************************************************
//
//     FILE: zceProcessRxWorker.cpp
//
//******************************************************************************

#include "zceProcessRxWorker.h"

#include "zceProcessRxPorts.h"

#include <sstream>

#include "../../Constants.h"
#include "../../Support.h"

using namespace std;

zceProcessRxWorker::zceProcessRxWorker( const ProcessRx_params& execParams, zcePushPorts_OctetSeqConsumerUsesPort* portDataOutData, zcePushPorts_OctetSeqConsumerUsesPort* portDataOutVoice ZCE_EXC_ENV_ARG ):
	portDataOutData_(portDataOutData), portDataOutVoice_(portDataOutVoice)
	#if defined(DEBUG_MSGS)
	, debug_(0)
	#endif

{
	ZCE_ASSERT_EXCEPTION_VOID;
	#if defined(DEBUG_MSGS)
	debug_.rdbuf(std::cout.rdbuf());
	#endif


	initExecParams(execParams ZCE_EXC_ENV_PARAM );

	// TODO : Implement constructor for zceProcessRxWorker
}

zceProcessRxWorker::~zceProcessRxWorker()
{
	// TODO : Implement destructor for zceProcessRxWorker
}

void zceProcessRxWorker::initExecParams( const ProcessRx_params& params ZCE_EXC_ENV_ARG)
{

	ZCE_ASSERT_EXCEPTION_VOID;
	execParams_.NAMING_CONTEXT_IOR = params.NAMING_CONTEXT_IOR;
	execParams_.NAME_BINDING = params.NAME_BINDING;
	execParams_.COMPONENT_IDENTIFIER = params.COMPONENT_IDENTIFIER;

	// TODO: perform some action based on these exec parameters
}

void zceProcessRxWorker::config_propDestinationId( const CORBA::String_var& propdestinationid  ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;

	mPropDestinationId = propdestinationid;
}

void zceProcessRxWorker::config_propModulation( const CORBA::Long& propmodulation  ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;

	mPropModulation = propmodulation;
}

void zceProcessRxWorker::config_propQoS( const CORBA::Long& propqos  ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;

	mPropQoS = propqos;
}

void zceProcessRxWorker::config_propApplicationType( const CORBA::Long& propapplicationtype  ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;

	mPropApplicationType = propapplicationtype;
}


void zceProcessRxWorker::query_propDestinationId( CORBA::String_var& propdestinationid  ZCE_EXC_ENV_ARG  )
{
	ZCE_ASSERT_EXCEPTION_VOID;

	propdestinationid = mPropDestinationId;
}

void zceProcessRxWorker::query_propModulation( CORBA::Long& propmodulation  ZCE_EXC_ENV_ARG  )
{
	ZCE_ASSERT_EXCEPTION_VOID;

	propmodulation = mPropModulation;
}

void zceProcessRxWorker::query_propQoS( CORBA::Long& propqos  ZCE_EXC_ENV_ARG  )
{
	ZCE_ASSERT_EXCEPTION_VOID;

	propqos = mPropQoS;
}

void zceProcessRxWorker::query_propApplicationType( CORBA::Long& propapplicationtype  ZCE_EXC_ENV_ARG  )
{
	ZCE_ASSERT_EXCEPTION_VOID;

	propapplicationtype = mPropApplicationType;
}



/*!	\brief
 *
 *	 Describe operation here.
 *
 *	\throw ::CF::LifeCycle::InitializeError
 *
 */
void zceProcessRxWorker::CF_LifeCycle_initialize( int portIdentifier ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
}

/*!	\brief
 *
 *	 Describe operation here.
 *
 *	\throw ::CF::LifeCycle::ReleaseError
 *
 */
void zceProcessRxWorker::CF_LifeCycle_releaseObject( int portIdentifier ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
}

/*!
 * \brief The start operation is provided to command a Resource implementing this
 * interface to start internal processing.
 *
 * Specification reference:  3.1.3.1.6.5.2
 *
 * The start operation puts the Resource in an operating condition.
 *
 * \return This operation does not return a value.
 *
 * \throw StartError The start operation shall raise the StartError exception if
 * an error occurs while starting the resource.
 *
 */
void zceProcessRxWorker::CF_Resource_start( int portIdentifier ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
}

/*!
 * \brief The stop operation is provided to command a Resource implementing this
 * interface to stop internal processing.
 *
 * Specification reference:  3.1.3.1.6.5.1
 *
 * The stop operation shall disable all current operations and put the Resource in
 * a non-operating condition. Subsequent configure, query, and start operations
 * are not inhibited by the stop operation.
 *
 * \return This operation does not return a value.
 *
 * \throw StopError The stop operation shall raise the StopError exception if an
 * error occurs while stopping the resource.
 *
 */
void zceProcessRxWorker::CF_Resource_stop( int portIdentifier ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
}

/*!	\brief
 *
 *	 Describe operation here.
 *
 *	\param msg ( ::CF::OctetSequence )
 *
 *	\param options ( ::CF::Properties )
 *
 */
void zceProcessRxWorker::PushPorts_OctetSeqConsumer_processOctetMsg( int portIdentifier, const CF::OctetSequence& msg, const CF::Properties& options ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;

	unsigned int propDestinationIdLength = CONST_HEADER_DESTINATION_ID_SIZE;
	unsigned int propApplicationTypeLength = CONST_HEADER_APPLICATION_TYPE_SIZE;
	unsigned int propQoSLength = CONST_HEADER_QOS_SIZE;
	unsigned int realDataLengthSizeLength = CONST_HEADER_REAL_DATA_LENGTH_SIZE;
	ostringstream destinationIdStream;
	ostringstream applicationTypeStream;
	ostringstream qosStream;
	ostringstream realDataLengthSizeStream;
	string destinationId;
	string applicationType;
	string qos;
	string realDataLengthSize;

	unsigned int headerLength = propDestinationIdLength + propApplicationTypeLength + propQoSLength + realDataLengthSizeLength;
	unsigned int processedMsgLength = msg.length() - headerLength;

	// Extract header
	CF::OctetSequence header(headerLength + 1);
	header.length(headerLength);

	int start = 0;
	int stop = header.length();

	for(unsigned int i = 0; i < header.length(); i++)
	{
		header[i] = CORBA::Octet(msg[i]);
		char chr = char(msg[i]);

		// Extract destinationId
		start = 0;
		stop = propDestinationIdLength;
		if((i >= start) && (i < stop))
		{
			destinationIdStream << chr;
		}

		// Extract applicationType
		start = propDestinationIdLength;
		stop = propDestinationIdLength + propApplicationTypeLength;
		if((i >= start) && (i < stop))
		{
			applicationTypeStream << chr;
		}

		// Extract QoS
		start = propDestinationIdLength + propApplicationTypeLength;
		stop = propDestinationIdLength + propApplicationTypeLength + propQoSLength;
		if((i >= start) && (i < stop))
		{
			qosStream << chr;
		}

		// Extract realDataLengthSize
		start = propDestinationIdLength + propApplicationTypeLength + propQoSLength;
		stop = propDestinationIdLength + propApplicationTypeLength + propQoSLength + realDataLengthSizeLength;
		if((i >= start) && (i < stop))
		{
			realDataLengthSizeStream << chr;
		}
	}

	destinationId = destinationIdStream.str();
	applicationType = applicationTypeStream.str();
	qos = qosStream.str();
	realDataLengthSize = realDataLengthSizeStream.str();

	ostringstream message;
	message << destinationId << "-" << applicationType << "-" << qos << "-" << realDataLengthSize << "-\n";
	logToFile("Debug", "ProcessRx", message.str());

	// Extract message
	CF::OctetSequence processedMsgVoice(processedMsgLength + 1);
	processedMsgVoice.length(processedMsgLength);

	CF::OctetSequence processedMsgData(msg.length() + 1);
	processedMsgData.length(msg.length());

	unsigned int realDataLengthSizeValue = atoi(realDataLengthSize.c_str());
	for(unsigned int i = 0; i < msg.length(); i++)
	{
		if((i >= headerLength) && (i < realDataLengthSizeValue + headerLength))
		{
			// Shift the data Modulation times
			CORBA::Octet tmp = msg[i];
			tmp = tmp - mPropModulation;
			processedMsgVoice[i - headerLength] = tmp;
			processedMsgData[i] = tmp;
		}
		else
		{
			processedMsgData[i] = msg[i];
		}
	}

	// Process message
	if(applicationType == "0")
	{
		// Voice
		portDataOutVoice_->processOctetMsg(processedMsgVoice, options);
	}
	else if(applicationType == "1")
	{
		// Data
		portDataOutData_->processOctetMsg(processedMsgData, options);
	}
	else
	{
		// Invalid application type
		logToFile("Debug", "ProcessRx", "Invalid application type\n");
	}
}


void zceProcessRxWorker::setportDataOutData( zcePushPorts_OctetSeqConsumerUsesPort& portDataOutData )
{
	portDataOutData_ = &portDataOutData;
}
void zceProcessRxWorker::setportDataOutVoice( zcePushPorts_OctetSeqConsumerUsesPort& portDataOutVoice )
{
	portDataOutVoice_ = &portDataOutVoice;
}

#if defined(DEBUG_MSGS)
void zceProcessRxWorker::setDebugStream(const std::ostream& stream)
{
	debug_.rdbuf(stream.rdbuf());
}

void zceProcessRxWorker::debugMsg(const std::string& msg)
{
	if(debug_ != NULL)
	{
		debug_ << msg << std::endl;
	}
}
#endif

// End-Of-File
//------------------------------------------------------------------------------
