//******************************************************************************************
//
//
//			september 16, 2004 :  Source file of the WaveForm Class
//
//		it contains the waveform raw data, at least there will be scaled
//		
//		author : X.Elattaoui
//
//******************************************************************************************



//- INCLUDE
#include "Waveform.h"
#include "SocketLecroy.h"
#include <iostream>
#include <string.h>

//using namespace std;

//- CTOR
WaveForm_data::WaveForm_data(std::string ch_name)
{
	//- initialisation of all Waveform attributes
	channel_name = ch_name;
	sh_raw_waveform_data = 0;
	vertical_scaled_waveform_data = 0;
	trigger_time_value = "Not available";
	//- the memory allocation is done in the get_waveform_data( ) method
	ptrRawData = 0;
}
//- DTOR
WaveForm_data::~WaveForm_data()
{
	if(ptrRawData)
	{
		delete [] ptrRawData;
		ptrRawData = 0;
	}
	if(sh_raw_waveform_data)
	{
		delete [] sh_raw_waveform_data;
		sh_raw_waveform_data = 0;
	}
	if(vertical_scaled_waveform_data)
	{
		delete [] vertical_scaled_waveform_data;
		vertical_scaled_waveform_data = 0;
	}

}

//- Method to return the channel name
std::string  WaveForm_data::get_channel_name( ) throw (lecroy::WaveformException)
{
	if( !channel_name.empty() )
		return channel_name;
	else
		throw lecroy::WaveformException("DATA_OUT_OF_RANGE ", 
										"get_channel_name( ) failed : channel_name is not initialized.",
										"WaveForm_data::get_channel_name( ).");
}
//- Method to set the channel name
void WaveForm_data::set_channel_name (std::string name)
{
	if( !name.empty() )
		channel_name = name;
}

//- Method to return the ptr on the WAVEDESC struct
WAVEDESC_BLOCK* WaveForm_data::get_wavedesc_descriptor( ) throw (lecroy::WaveformException)
{
	if(waveBlockData)
		return waveBlockData;
	else
		throw lecroy::WaveformException("DESCRIPTOR_MEMORY_ ", 
										"get_waveform_data( ) method must be called before.",
										"WaveForm_data::get_wavedesc_descriptor( ).");

}

//- Method to return the raw data of the acquired waveform
void WaveForm_data::get_waveform_data( ) throw (lecroy::WaveformException)
{
std::string	cmd("");
char*	cmdStr = 0;
//int	ulTrace_Size = 0;
int		response_length=0;
short	OFFSET_STRUCT = 0;

	//- init ptr WaveBlocData which point on WAVEDESC_BLOCS structure
	waveBlockData = 0;

	//- get channel name
	std::string ch_name("") ;

	ch_name = get_channel_name();
	//- prepare the cmd to get the waveform data
	cmd = ch_name + ":WF? ALL";
	cmdStr = new char[cmd.size()+1];
	std:strcpy(cmdStr, cmd.c_str());
	int length = strlen(cmdStr);

	//- send the request
	SocketLecroy::get_instance( )->TCP_WriteDevice(cmdStr,length,true);

	//- delete cmd allocation
	if(cmdStr)
	{
		delete [] cmdStr;
		cmdStr = 0;
	}
	
	//- first desallocate previous data 
	if (ptrRawData)
	{
		delete [] ptrRawData;
		ptrRawData = 0;
	}

	//- delete previous raw data
	if(sh_raw_waveform_data)
	{
		delete [] sh_raw_waveform_data;
		sh_raw_waveform_data = 0;
	}
	
	//- delete previous scaled data
	if(vertical_scaled_waveform_data)
	{
			delete [] vertical_scaled_waveform_data;
			vertical_scaled_waveform_data = 0;
	}

	//- allocate memory for the receive data (WaveDesc + data)
	ptrRawData = new char[MAX_WAVEFORM_DATA_LENGTH];
	length = MAX_WAVEFORM_DATA_LENGTH;
	if(!ptrRawData)
		throw lecroy::WaveformException("OUT_OF_MEMORY", 
										"The pointer (ptrRawData) for the receive data can't be allocated before the read operation.",
										"WaveForm_data::get_waveform_data( ).");
	//- read the response
	try
	{
		SocketLecroy::get_instance( )->TCP_ReadDevice(ptrRawData,length,&response_length);
	}
	catch(const lecroy::WaveformException &)
	{
		//- XE : 
		throw lecroy::WaveformException("OPERATION_FAILED", 
										"The TCP_ReadDevice() method failed.",
										"WaveForm_data::get_waveform_data( ).");
	}

	//- calculation of the offset of the structure (it can be 15 or 21)
	long i = 0;
	for(i=0; i < 22 ; i++)
	{
		if(ptrRawData[i] == 'W' && ptrRawData[i+1] == 'A')
		{
			//- the offset of the structure which contains the context of the waveform acquisition
			OFFSET_STRUCT = i;
		}
	}

	//- test if the OFFSET_STRUCT is found
	if(!OFFSET_STRUCT)
		throw lecroy::WaveformException("DATA_OUT_OF_RANGE", 
					"The offset of the structure is not found.",
					"WaveForm_data::get_waveform_data( ).");


	//- update the struct WAVEDESC_BLOC
	waveBlockData = (WAVEDESC_BLOCK*) (ptrRawData+OFFSET_STRUCT);
	if(!waveBlockData)
		throw lecroy::WaveformException("OUT_OF_MEMORY", 
										"The pointer for the receive data can't be allocated before the read operation.",
										"WaveForm_data::get_waveform_data( ).");

	//- allocate memory for the raw data
	sh_raw_waveform_data = new short[waveBlockData->wave_array_count];
	if(!sh_raw_waveform_data)
		throw lecroy::WaveformException("OUT_OF_MEMORY", 
										"The pointer for the receive data can't be allocated before the read operation.",
										"WaveForm_data::get_waveform_data( ).");

	//- allocate memory for the vertical scaled data
	vertical_scaled_waveform_data = new double[waveBlockData->wave_array_count];
	if(!vertical_scaled_waveform_data)
		throw lecroy::WaveformException("OUT_OF_MEMORY", 
										"The pointer for the scaled data can't be allocated before the read operation.",
										"WaveForm_data::get_waveform_data( ).");

	//- copy the data before sending them
	for( i=0; i<waveBlockData->wave_array_count ; i++)
	{
		sh_raw_waveform_data[i] =  (ptrRawData + OFFSET_STRUCT + waveBlockData->wave_descriptor)[i];
		//- Found in the "Remote Control Manual" : calculation of the vertical scaled data
		vertical_scaled_waveform_data[i] = (waveBlockData->vertical_gain * sh_raw_waveform_data[i]) - waveBlockData->vertical_offset;
	}

}

//- return the ptr on sh_raw_waveform_data ( = the waveform data acquired)
short* WaveForm_data::get_raw_waveform_data () throw (lecroy::WaveformException)
{
	if(sh_raw_waveform_data)
		return sh_raw_waveform_data;
	else
		throw lecroy::WaveformException("DESCRIPTOR_MEMORY_ ", 
										"get_waveform_data( ) method must be called before.",
										"WaveForm_data::get_raw_waveform_data( ).");

}


//- Method to return the scaled data of the acquired waveform
double* WaveForm_data::get_vertical_scaled_waveform_data( ) throw (lecroy::WaveformException)
{
	
	if(vertical_scaled_waveform_data)
		return vertical_scaled_waveform_data;
	else
		throw lecroy::WaveformException("DESCRIPTOR_MEMORY_ ", 
										"get_waveform_data( ) method must be called before.",
										"WaveForm_data::get_vertical_scaled_waveform_data( ).");
}

//- Method to return the trigger time of the acquired waveform

std::string	WaveForm_data::get_trigger_time_value ( )
{
	
	//- The format is : "Date = month, day, year ; Time = hours:minutes:seconds"
	std::string str_seconds("");
	std::string str_minutes("");
	std::string str_hours  ("");
	std::string str_days   ("");
	std::string str_months ("");
	std::string str_years  ("");
	
	//- hours, min, sec with 2 digits
	str_seconds = XString<double>::convertToString(waveBlockData->trigger_time_seconds);
	if(waveBlockData->trigger_time_seconds<10)
		str_seconds = "0" + str_seconds;

	str_minutes = XString<int>::convertToString((int)waveBlockData->trigger_time_minutes);
	if(waveBlockData->trigger_time_minutes<10)
		str_minutes = "0" + str_minutes;
	
	str_hours	= XString<int>::convertToString(waveBlockData->trigger_time_hours);
	if(waveBlockData->trigger_time_hours<10)
		str_hours = "0" + str_hours;

	str_days	= XString<int>::convertToString(waveBlockData->trigger_time_days);
	str_months	= XString<int>::convertToString(waveBlockData->trigger_time_months);
	str_years	= XString<short>::convertToString(waveBlockData->trigger_time_year);

	//- Construct the string Trigger Time:
	trigger_time_value = "Date = " + str_months + "/" + str_days + "/" + str_years + " ; Time = " + str_hours + ":" + str_minutes + ":" + str_seconds;
	
	return trigger_time_value;
}