//=========================================================================
// Summary  :
// Filename : MMUtils.h
// Author   : paley
// Project  :
// Revision : 1
// Created  : 2001/05/17
// Modified : 2001/05/17
//=========================================================================
// Description :  Utility message classes
//=========================================================================
#ifndef _MMUTILS_H
#define _MMUTILS_H

#include "ModemMessage.h"

#define UtilsMessageTimeOut 30

#define uchar unsigned char
#define ushort unsigned short

#ifndef PI
#define PI          3.14159265358979323846
#endif

////////////////////////////////////////////////////
#define REQ_MIN_PD 			0			//Seconds
#define REQ_MAX_PD 			255			//Seconds
#define MIN_PROP_RPM		-500		//Rpm
#define MAX_PROP_RPM		500			//Rpm
#define MIN_ACT_ANGLE		-0.3		//Rad
#define MAX_ACT_ANGLE		0.3			//Rad
#define MIN_HDG_ANGLE		0			//Degrees
#define MAX_HDG_ANGLE		360			//Degrees
#define MIN_SPEED			-5.0		//Meters/second
#define MAX_SPEED			5.0			//Meters/second
#define MIN_DEPTH			0			//Meters
#define MAX_DEPTH			4000		//Meters
#define MIN_ALTITUDE		0			//Meters
#define MAX_ALTITUDE		1000		//Meters
#define MIN_TIP_ANGLE		-0.7854 	//Rad
#define MAX_TIP_ANGLE		0.7854		//Rad
#define MIN_TIP_RATE		-0.7854 	//Rad/sec
#define MAX_TIP_RATE		0.7854		//Rad/sec
#define MIN_CIRCUIT_CUR		0.0			//Amps
#define MAX_CIRCUIT_CUR		15.0		//Amps
#define MIN_GFAULT_CUR		0.0			//Ohms (not a current!)
#define MAX_GFAULT_CUR		2000.0		//Ohms (not a current!)
#define MIN_TEMP			0.0			//Celsius
#define MAX_TEMP			100.0		//Celsius
#define MIN_PRESSURE		0.0			//PSI
#define MAX_PRESSURE		6000.0		//PSI
#define MIN_CURRENT			0.			//Amps
#define MAX_CURRENT			25.			//Amps
#define MIN_VOLTAGE			24.			//Volts
#define MAX_VOLTAGE			34.			//Volts
#define MIN_CELL_VOLTAGE	0.			//Volts
#define MAX_CELL_VOLTAGE	5.			//Volts
#define MIN_RANGE			0.			//Meters
#define MAX_RANGE			200.		//Meters
#define MIN_AZIMUTH 		-PI/2.		//Rads
#define MAX_AZIMUTH			PI/2.		//Rads
#define MIN_HDOP			0.
#define MAX_HDOP			20.

////////////////////////////////////////////////////
#define NUM_WATER_ALARMS	4

////////////////////////////////////////////////////
class MMUtil
{
public:
	static uchar int2char(int value);
	static int char2int(uchar value);
	static uchar int2char(int value, int min, int max);
	static int char2int(uchar value, int min, int max);
	static uchar double2char(double value, double min, double max);
	static double char2double(uchar value, double min, double max);
	static ushort double2short(double value,double min,double max);
	static double short2double(ushort value,double min,double max);
	static long int Rnd(double num_in);
	static double modPi( double angle );
	static double radToDeg(double rad) { return rad*180./PI; }
	static double degToRad(double deg) { return deg/180.*PI; }
	static short getServer(const char *device);
	static void getHHMMss(char * str);
	static void stringToSNS(char * str, int* seconds, int *nanoseconds);
	static double MMUtil::longitude(const char *token);
	static char* MMUtil::longitude(double value);
	static double MMUtil::latitude(const char *token);
	static char* MMUtil::latitude(double value);
};

////////////////////////////////////////////////////
// Not for instantiation!
class MMNumberedBoolean : public MMConvertible
{

public:
	MMNumberedBoolean() {};
	MMNumberedBoolean(const ModemMessage *pMM);
	MMNumberedBoolean(int number, Boolean value);

	virtual const char* pcRead(const char* sourceBuffer);
	virtual char* pcWrite(char* destBuffer) const;
	virtual ModemMessage::Type tGetMessageType() const
		{ return ModemMessage::tUNKNOWN; };
	virtual int iGetDefaultTimeout() const
		{ return UtilsMessageTimeOut; };

	virtual int getNumber()
		{ return MMUtil::char2int(m_number); };
	virtual void setNumber(int number)
		{ m_number = MMUtil::int2char(number); };
	virtual Boolean getValue()
		{ return m_value; };
	virtual void setValue(Boolean value)
		{ m_value = value; };

	static int size() { return 2; };

protected:
	// WARNING: can only store 0 to 255 here!
	uchar m_number;
	Boolean m_value;

};

////////////////////////////////////////////////////
// Not for instantiation!
class MMBooleanArray : public MMConvertible
{

public:
	MMBooleanArray() {};
	MMBooleanArray(const ModemMessage *pMM);
	MMBooleanArray(int number);

	virtual const char* pcRead(const char* sourceBuffer);
	virtual char* pcWrite(char* destBuffer) const;
	virtual ModemMessage::Type tGetMessageType() const
		{ return ModemMessage::tUNKNOWN; };
	virtual int iGetDefaultTimeout() const
		{ return UtilsMessageTimeOut; };

	int getNumber()
		{ return MMUtil::char2int(m_number); };
	Boolean getValue(int number);
	void setValue(int number, Boolean value);

	static int size(int n) { return n+1; };

protected:
	// WARNING: can only store 0 to 255 here!
	uchar m_number;
	Boolean m_value[256];
};

////////////////////////////////////////////////////
// Not for instantiation!
class MMNumberedFloat : public MMConvertible
{

public:
	MMNumberedFloat() {};
	MMNumberedFloat(const ModemMessage *pMM);
	MMNumberedFloat(int number, float value, float min, float max);

	virtual const char* pcRead(const char* sourceBuffer);
	virtual char* pcWrite(char* destBuffer) const;
	virtual ModemMessage::Type tGetMessageType() const
		{ return ModemMessage::tUNKNOWN; };
	virtual int iGetDefaultTimeout() const
		{ return UtilsMessageTimeOut; };

	virtual int getNumber()
		{ return MMUtil::char2int(m_number); };
	virtual void setNumber(int number)
		{ m_number = MMUtil::int2char(number); }
	float getValue(float min, float max)
		{ return MMUtil::char2double(m_value,min,max); };
	void setValue(float value, float min, float max)
		{ m_value = MMUtil::double2char(value,min,max); };

	static int size() { return 2; };

protected:
	// WARNING: can only store 0 to 255 here!
	uchar m_number;
	uchar m_value;
};

////////////////////////////////////////////////////
// Not for instantiation!
class MMFloatArray : public MMConvertible
{

public:

    enum FloatArrayTypes{
	Chars = 0,
	Shorts
    };
	
    MMFloatArray() {};
    MMFloatArray(const ModemMessage *pMM);
    MMFloatArray(int number, int type = Chars);
    
    virtual const char* pcRead(const char* sourceBuffer);
    virtual char* pcWrite(char* destBuffer) const;
    virtual ModemMessage::Type tGetMessageType() const
	{ return ModemMessage::tUNKNOWN; };
    virtual int iGetDefaultTimeout() const
	{ return UtilsMessageTimeOut; };
    
    int getNumber()
	{ return MMUtil::char2int(m_number); };
    int getType()
	{ return MMUtil::char2int(m_type); };
    float getValue(int number, float min, float max);
    void setValue(int number, float value, float min, float max);
    void setType(int type) {
	m_type = MMUtil::int2char(type);
	m_dataType = ((type == 0) ? Chars : Shorts);
    }

    static int size(int n) { return n+1; };
    
 protected:
    FloatArrayTypes m_dataType;
    uchar m_type;

    uchar m_number;

    //not all of these will be sent of course
    //had to remain m_value for backwards compatability
    uchar m_value[256];
    ushort m_shortValue[256];
    
};

#endif
