//=========================================================================
// Summary  :
// Filename : MMBehavior.h
// Author   : Gil Jones
// Project  :
// Revision : 1
// Created  : 2001/11/15
// Modified : 2001/11/15
//=========================================================================
// Description :  Change behavior attributes
//=========================================================================

#include <stdio.h>
#include "MMBehavior.h"

MMBehavior::MMBehavior(const ModemMessage *pMM)
{
    Assert(pMM);
    Assert(pMM->getType()==tGetMessageType());
    const char* pcEnd = pcRead(pMM->getBuffer());
    Assert(pcEnd==pMM->getBuffer()+pMM->getBufferSize());
}

MMBehavior::MMBehavior(short stateNum, short priorityNum,
			   short nameSize, char* name,
			   short dataSize, char* data) 
{
    
    _success = -1;
 
    _stateNum = stateNum;
    _priorityNum = priorityNum;
    Assert(nameSize <= 32*sizeof(char));
    _nameSize = nameSize;
    memcpy(_name, name, _nameSize);
    Assert(dataSize <= 64*sizeof(char));
    _dataSize = dataSize;
    memcpy(_data, data, _dataSize);
}

MMBehavior::MMBehavior(short success){

    _stateNum = 0;
    _priorityNum = 0;
    _nameSize = 0;
    _dataSize = 0;
    _success = success;
}
    
const char* MMBehavior::pcRead(const char* sourceBuffer)
{
    const char* pcEnd = ::pcRead(sourceBuffer, &_stateNum);
    pcEnd = ::pcRead(pcEnd, &_priorityNum);
    pcEnd = ::pcRead(pcEnd, &_nameSize);
    Assert(_nameSize <= 32*sizeof(char));    
    if(_nameSize != 0){
	memset(_name, 0, 32);
	memcpy(_name, pcEnd, _nameSize);
	//fprintf(stdout, "Name: %s\n", _name);
	pcEnd+=_nameSize;
    }
    pcEnd = ::pcRead(pcEnd, &_dataSize);
    Assert(_dataSize <= 64*sizeof(char));
  
    if(_dataSize != 0){
	memset(_data, 0, 64);
	memcpy(_data, pcEnd, _dataSize);
	//fprintf(stdout, "Data: %s\n", _data);
	pcEnd+=_dataSize;
    }
    pcEnd = ::pcRead(pcEnd, &_success);
    return pcEnd;
}

char* MMBehavior::pcWrite(char* destBuffer) const
{
    char *pcEnd = ::pcWrite(destBuffer, _stateNum);
    pcEnd = ::pcWrite(pcEnd, _priorityNum);
    pcEnd = ::pcWrite(pcEnd, _nameSize);
    if(_nameSize != 0){
	memcpy(pcEnd, _name, _nameSize);
	pcEnd+=_nameSize;
    }
    pcEnd = ::pcWrite(pcEnd, _dataSize);
    if(_dataSize != 0){
	memcpy(pcEnd, _data, _dataSize);
	pcEnd+=_dataSize;
    }
    pcEnd = ::pcWrite(pcEnd, _success);
    return pcEnd;
}

MMBehaviorArray::MMBehaviorArray(const ModemMessage *pMM)
{
    Assert(pMM);
    Assert(pMM->getType()==tGetMessageType());
    const char* pcEnd = pcRead(pMM->getBuffer());
    Assert(pcEnd==pMM->getBuffer()+pMM->getBufferSize());
}

MMBehaviorArray::MMBehaviorArray(short numChanges, short *states, short* priorities, short* nameSizes, 
				 char** names, short* dataSizes, char** data)
{

    _states = NULL;
    _priorities = NULL;
    _nameSizes = NULL;;
    _dataSizes = NULL;
    _names = NULL;
    _data = NULL;
    _successes = NULL;

    _numChanges = numChanges;
    _numSuccesses = 0;

    _states = new short[_numChanges];
    _priorities = new short[_numChanges];
    _nameSizes = new short[_numChanges];
    _dataSizes = new short[_numChanges];
    _names = (Name *) malloc (sizeof(Name)*_numChanges);
    _data = (Data *) malloc (sizeof(Data)*_numChanges);

    memcpy(_states, states, sizeof(short)*_numChanges);
    memcpy(_priorities, priorities, sizeof(short)*_numChanges);
    memcpy(_nameSizes, nameSizes, sizeof(short)*_numChanges);
    memcpy(_dataSizes, dataSizes, sizeof(short)*_numChanges);

    for(int i=0; i <_numChanges; i++){
	strcpy(_names[i], names[i]);
	strcpy(_data[i], data[i]);
    }    
}

MMBehaviorArray::MMBehaviorArray(short numSuc, short* successes)
{
    _states = NULL;
    _priorities = NULL;
    _nameSizes = NULL;;
    _dataSizes = NULL;
    _names = NULL;
    _data = NULL;
    _successes = NULL;

    _numChanges = 0;
    _numSuccesses = numSuc;
    _successes = (short *)malloc(sizeof(short)*numSuc);
    memcpy(_successes, successes, sizeof(short)*numSuc);
}

MMBehaviorArray::~MMBehaviorArray()
{
    if(_priorities != NULL) delete _priorities;
    if(_nameSizes != NULL) delete _nameSizes;
    if(_dataSizes != NULL) delete _dataSizes;
    if(_successes != NULL) delete _successes;
    if(_names != NULL) free(_names);
    if(_data != NULL) free( _data);
}

const char* MMBehaviorArray::pcRead(const char* sourceBuffer)
{

    char temp[64];
    char rc[2] = {0x1,0x0};
    int k,i;
    const char* pcEnd = ::pcRead(sourceBuffer, &_numChanges);
    pcEnd = ::pcRead(pcEnd, &_numSuccesses);

    //allocate memory based on _numChanges
    _states = new short[_numChanges];
    _priorities = new short[_numChanges];
    _nameSizes = new short[_numChanges];
    _dataSizes = new short[_numChanges];
    _successes = (short *)malloc(sizeof(short)*_numSuccesses);
    _names = (Name *) malloc (sizeof(Name)*_numChanges);
    _data = (Data *) malloc (sizeof(Data)*_numChanges);

    //    fprintf(stdout, "NumChanges: %d\n", _numChanges);

    if(_numChanges != 0){
	for(i=0;i<_numChanges;i++){
	    pcEnd = ::pcRead(pcEnd, &_states[i]);
	}
	for(i=0;i<_numChanges;i++){
	    pcEnd = ::pcRead(pcEnd, &_priorities[i]);
	}
	for(i=0;i<_numChanges;i++){
	    pcEnd = ::pcRead(pcEnd, &_nameSizes[i]);
	}
	for(i=0; i < _numChanges; i++) {

	    if(_nameSizes[i] != 0){
		memset(temp, 0, 32);
		for(int x = 0; x < _nameSizes[i]; x++) {
		    temp[x] = pcEnd[0];
		    pcEnd++;
		}
		strcpy(_names[i], temp);
		//fprintf(stdout, "Behavior Name: %s\n", _names[i]);
	    }
	}
	for(i=0;i<_numChanges;i++){
	    pcEnd = ::pcRead(pcEnd, &_dataSizes[i]);
	}
	for(int j=0; j < _numChanges; j++) {
	
	    if(_dataSizes[j] != 0){
		//fprintf(stdout, "size2: %d\n", _dataSizes[j]);
		memset(temp, 0, 64);
		//for some reason, no matter what there was garbage
		for(int t = 0; t < _dataSizes[j]; t++) {
		    temp[t] = pcEnd[0];
		    pcEnd++;
		}
		strcpy(_data[j], temp);
		//fprintf(stdout, "Behavior Data: %s\n", _data[j]);
	    }
	}
    }
    if(_numSuccesses != 0){
	for(i=0;i<_numSuccesses;i++){
	    pcEnd = ::pcRead(pcEnd, &_successes[i]);
	}	
    }
    return pcEnd;
}

char* MMBehaviorArray::pcWrite(char* destBuffer) const
{
    int i;

    char* pcEnd = ::pcWrite(destBuffer, _numChanges);
    pcEnd = ::pcWrite(pcEnd, _numSuccesses);
    
    if(_numChanges != 0){
	for(i=0;i<_numChanges;i++){
	    pcEnd = ::pcWrite(pcEnd, _states[i]);
	}
	for(i=0;i<_numChanges;i++){
	    pcEnd = ::pcWrite(pcEnd, _priorities[i]);
	}
	for(i=0;i<_numChanges;i++){
	    pcEnd = ::pcWrite(pcEnd, _nameSizes[i]);
	}
	for(i=0; i < _numChanges; i++) {
	    if(_nameSizes[i] != 0){
		memcpy(pcEnd, _names[i], sizeof(char)*_nameSizes[i]);
		pcEnd += sizeof(char)*_nameSizes[i];
	    }
	}
	for(i=0;i<_numChanges;i++){
	    pcEnd = ::pcWrite(pcEnd, _dataSizes[i]);
	}
	for(int j=0; j < _numChanges; j++) {
	    if(_dataSizes[j] != 0){
		memcpy(pcEnd, _data[j], sizeof(char)*_dataSizes[j]);
		pcEnd += sizeof(char)*_dataSizes[j];
		//fprintf(stdout, "Writing %s size %d\n", _data[j], _dataSizes[j]);
	    }
	}
    }
    if(_numSuccesses != 0){
	for(i=0;i<_numSuccesses;i++){
	    pcEnd = ::pcWrite(pcEnd, _successes[i]);
	}
    }
    return pcEnd;
}

short MMBehaviorArray::getSingleState(int i) 
{
    return(_states[i]);
}

void MMBehaviorArray::getAllStates(short* p)
{
    p = new short[_numChanges];
    memcpy(p, _states, sizeof(short)*_numChanges);
}

short MMBehaviorArray::getSinglePriority(int i) 
{
    return(_priorities[i]);
}

void MMBehaviorArray::getAllPriorities(short* p)
{
    p = new short[_numChanges];
    memcpy(p, _priorities, sizeof(short)*_numChanges);
}

void MMBehaviorArray::getSingleName(int i, char* nameBuf)
{
    strcpy(nameBuf, _names[i]);
}

void MMBehaviorArray::getAllNames(char** nameBufs) {
    
    for(int i = 0; i < _numChanges; i++){
	//nameBufs[i] = new char(_nameSizes[i]);
	strcpy(nameBufs[i], _names[i]);
    }
}

void MMBehaviorArray::getSingleData(int i, char* dataBuf) {

    //dataBuf = new char(_dataSizes[i]);
    strcpy(dataBuf, _data[i]);
}

void MMBehaviorArray::getAllData(char** dataBufs){
    
    //dataBufs = new char*(_numChanges);

    for(int i = 0; i < _numChanges; i++) {
	//dataBufs[i] = new char(_dataSizes[i]);
	strcpy(dataBufs[i], _data[i]);
    }
}

short MMBehaviorArray::getSingleSuccess(int i){
    return _successes[i];
}

void MMBehaviorArray::getAllSuccesses(short* b){
    
    b = (short *)malloc(sizeof(short)*_numSuccesses);
    memcpy(b,_successes, sizeof(short)*_numSuccesses);
}
