/*******************************************************************************
 * Copyright (c) 2005, 2009 IBM, Intel Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Guru Nagarajan, Intel - initial API and implementation
 *    IBM - Initial Java API and implementation
 *
 * $Id: ControlMessage.cpp,v 1.23 2009/08/26 14:59:51 jwest Exp $
 *
 *******************************************************************************/ 

#include "tptp/client/ControlMessage.h"
#include "tptp/client/CommandFragment.h"
#include "tptp/client/Constants.h"
#include "tptp/client/TPTP_XMLHandler.h"
#include "tptp/NoLog.h"
#include "tptp/TPTPUtils.h"

#ifdef MVS
	#include <unistd.h>
	#define NATIVE_BUFFER_SIZE 65536
#endif

using namespace std;


#if defined(__x86_64__)
static SAXParser *parser = NULL;
#endif

int getCtxCommand(const char *input, char **src, char **dest, char **ctxt);


ControlMessage::ControlMessage()
{
	this->_type=Constants::RA_CONTROL_MESSAGE;
#if defined(__x86_64__)
	if (parser == NULL) {
		parser = new SAXParser();
	}
#endif
}

ControlMessage::~ControlMessage()
{ 
}

unsigned int ControlMessage::getSize()
{
	int size=0;
	size=Message::getSize();

	size += Constants::sizeofLong;

	if (this->_entries.size()  >0)
	{
		for(unsigned int i=0; i<this->_entries.size(); i++)
		{
			size += this->_entries[i]->getSize();
		}
	}
	
	return  size;
}

void ControlMessage::appendCommand(CommandElement *command)
{
	if(this->_entries.size() == 0 ) 
	{
		this->_entries.push_back(command);
		return;
	}
}

CommandElement* ControlMessage::getCommand(int offset)
{ 
	return this->_entries[offset]; 
}

unsigned long ControlMessage::getLength()
{ 
	return this->_length; 
}

TPTP_String ControlMessage::getKey()
{ 
	return this->_key; 
}

void ControlMessage::setKey(TPTP_String key)
{ 
	this->_key = key;	
}

unsigned int ControlMessage::getCommandCount()
{
	int commandcount = this->_entries.size();
	return commandcount;
}


/**********************************************************************
************************************************************************/
unsigned char* ControlMessage::readFromBuffer(unsigned char *buffer,unsigned int offset)
{
	unsigned char *current = buffer;
	unsigned int intt = 0;
	current = Message::readFromBuffer(current, offset);


	#if (defined(__linux__) && defined(__s390__)) || defined(_SOLARIS) || defined(_AIX) || defined(MVS)
		current = Message::readTPTPUINTFromBuffer(current, (unsigned int*)&intt);
		_length = intt;
	#else
		current = Message::readTPTPUINTFromBuffer(current, (unsigned int*)&_length);		
	#endif

	#ifdef MVS
		// Convert returned message from the Agent Controller socket to native
		__atoe((char *)current);
	#endif
	int count=0;
	
	string Temp;
	Temp = (char *)current;
	string temp = Temp.substr(offset, Temp.length() - offset);
	int startIndex = 0;
    int retIndex = startIndex;
    while (retIndex > 0 || ((int)string::npos != retIndex))
    {
      retIndex = temp.find(CMD_CLOSE_TAG, startIndex);
      if (retIndex > 0)
      {
        startIndex = retIndex+1;
        count++;
      }
    
    }
    
	vector<string> tempvec;
	int startIndexOfcmd = 0;
    int retIndexOfCmd = startIndexOfcmd;
    while (retIndexOfCmd > 0 || ((int)string::npos != retIndexOfCmd))
    {
      retIndexOfCmd = Temp.find(CMD_CLOSE_TAG, startIndexOfcmd);
	  if((int)string::npos == retIndexOfCmd){break;}
	  tempvec.push_back(Temp.substr(startIndexOfcmd,retIndexOfCmd-startIndexOfcmd+strlen(CMD_CLOSE_TAG)));
      startIndexOfcmd = retIndexOfCmd+strlen(CMD_CLOSE_TAG);
	} 
	
	if (count > 0)
    {
		for(int i=0; i<count; i++) 
        {
           CommandElement* command;
           command=new CommandFragment();
		   int			src, ctxt,dest;
		   char			*cmdName;
		   char			*interfaceID;
		   tptp_list_t	*parmList;

		   //for(unsigned int vecsize = 0; vecsize < tempvec.size(); vecsize++)
		   //{ 
				//getCtxCommand(tempvec[i].c_str(), &src, &dest, &ctxt);
			int ret = parseCommand(tempvec[i].c_str(),&src,&ctxt,&interfaceID, &cmdName, &parmList);
			//char* cmd = (char*)malloc(strlen(tempvec[i].c_str()));
			//strcpy(cmd, tempvec[i].c_str());
			
			ret = getDestinationID(tempvec[i].c_str(),&dest);
			
			command->setCommand((char *)tempvec[i].c_str());
			command->setCommandName(cmdName);
			command->setContext(ctxt);
		    command->setSource(src);
		    command->setDestination(dest);
			
			//}
		   
#if !defined(__ia64__) && !defined(__x86_64__) && !defined(__64BIT__)
		   tptp_free(cmdName);
		   tptp_free(parmList);
#endif

           current=command->readFromBuffer(current, offset);
		    
           this->_entries.push_back(command);
		 }
	}
	
   return current;
 
}//end this->readfrombuffer

#ifndef MVS
	unsigned char* ControlMessage::writeToBuffer(unsigned char *buffer,unsigned int offset)
	{
		unsigned char* current;
		current = buffer;
		current = Message::writeToBuffer(current, offset);
		
		int payLoadSize = 0;
		if (this->_entries.size() >0)
		{
			for(unsigned int i=0; i< this->_entries.size(); i++)
			{
				payLoadSize += this->_entries[i]->getSize();
			}
		}
		this->_length = payLoadSize;

		current= Message::copyTPTPUINTToBuffer(current, this->_length);
		if (this->_entries.size() >0)
		{
			for(unsigned int i=0; i<_entries.size(); i++) 
			{
				current=this->_entries[i]->writeToBuffer(current,offset);
			}
		}
		TPTP_LOG_DEBUG_MSG1("Entries count -> : %d", this->_entries.size());
		
		return current;
	}
#else
	unsigned char* ControlMessage::writeToBuffer(unsigned char *buffer,unsigned int offset)
	{
		unsigned char* current;
		current = buffer;
		current = Message::writeToBuffer(current, offset);
		char *nativeBuffer = (char *)tptp_malloc(NATIVE_BUFFER_SIZE);

		int payLoadSize = 0;
		if (this->_entries.size() >0)
		{
				for(unsigned int i=0; i< this->_entries.size(); i++)
				{
						 nativeBuffer=(char*)this->_entries[i]->writeToBuffer((unsigned char*)nativeBuffer,offset);
				}
		}
		char *unicodeBuffer  = (char *)tptp_malloc(strlen(nativeBuffer)+1);
		native2unicode(&unicodeBuffer, nativeBuffer, strlen(nativeBuffer));
		this->_length = strlen(unicodeBuffer);
		current= Message::copyTPTPUINTToBuffer(current, this->_length);
		current= Message::copyTPTPSTRINGToBuffer(current, unicodeBuffer);
		if(nativeBuffer != 0) {
			   tptp_free(nativeBuffer);
		}
		if(unicodeBuffer != 0) {
			   tptp_free(unicodeBuffer);
		}
		return current;
	}
#endif
/*
int getCtxCommand(const char *input, char **src, char **dest, char **ctxt) 
{
	int ret = parseCommand(input, src, dest, ctxt);
	return 0;
}
*/

