// Copyright (c) 2020 Metrolab Technology S.A., Geneva, Switzerland (www.metrolab.com)
// See the included file LICENSE.txt for the licensing conditions.

//////////////////////////////////////////////////////////////////////////
/// \file
/// \brief THM1176 API: type conversion utilities.

// Standard includes
#include <cfloat>

// Personal includes
#include "THM1176TypeConversions.h"
#include "SCPIInstrumentBuffer.h"
#include "Helpers.h"
#include "OSDefines.h"

// Microsoft compilers don't define endianness.
#if _WIN32
	#define __LITTLE_ENDIAN__ 1

// GNU compilers define it in <endian.h>
#elif __linux__
	#include <endian.h>
	#if __BYTE_ORDER == __LITTLE_ENDIAN
		#define __LITTLE_ENDIAN__ 1
	#else
		#define __BIG_ENDIAN__ 1
	#endif
#endif

using namespace MTL::Instrument;

namespace MTL {
	namespace Instrument {
		namespace THM1176Types {
			
			I16 BinaryToI16(const char pBinary[2])
			{
#if __LITTLE_ENDIAN__
				const char Binary16_Out[2] = { pBinary[1], pBinary[0] };
				return *(I16*)Binary16_Out;
#elif __BIG_ENDIAN__
				return *(I16*)pBinary;
#else
				#error Neither __LITTLE_ENDIAN__ nor __BIG_ENDIAN__ is defined.
#endif
			}
			I32 BinaryToI32(const char pBinary[4])
			{
#if __LITTLE_ENDIAN__
				const char Binary32_Out[4] = { pBinary[3], pBinary[2], pBinary[1], pBinary[0] };
				return *(I32*)Binary32_Out;
#elif __BIG_ENDIAN__
				return *(I32*)pBinary;
#else
				#error Neither __LITTLE_ENDIAN__ nor __BIG_ENDIAN__ is defined.
#endif
			}
			bool StringToUnits(std::string SUnits, eUnits & rUnits)
			{
				if		(SUnits == "T")			rUnits = kT;
				else if (SUnits == "MT")		rUnits = kmT;
				else if (SUnits == "UT")		rUnits = kuT;
				else if (SUnits == "NT")		rUnits = knT;
				else if (SUnits == "GAUSs")		rUnits = kGauss;
				else if (SUnits == "KGAUss")	rUnits = kkGauss;
				else if (SUnits == "MGAUss")	rUnits = kmGauss;
				else if (SUnits == "MAHZp")		rUnits = kMHzp;
				else return false;
				
				return true;
			}
			std::string UnitsToString(eUnits Units)
			{
				return	Units == kT ?			"T" :
						Units == kmT ?			"MT" :
						Units == kuT ?			"UT" :
						Units == knT ?			"NT" :
						Units == kGauss ?		"GAUSs" :
						Units == kkGauss ?		"KGAUss" :
						Units == kmGauss ?		"MGAUss" :
						Units == kMHzp ?		"MAHZP" : "";
			}
			
			//----------------------------------------------------------------------//
			//									TESTS								//
			//----------------------------------------------------------------------//
			bool TestTHM1176Types()
			{
				try
				{
					//----------------------------------------------------------------------//
					//								Binary Numbers							//
					//----------------------------------------------------------------------//
					char Binary16[2] = { '\x12', '\xF3' };
					if (BinaryToI16(Binary16) != 4851)
						throw "Invalid I16 conversion";
					char Binary32[4] = { '\x12', '\x34', '\x56', '\xF7' };
					if (BinaryToI32(Binary32) != 305420023)
						throw "Invalid I32 conversion";
				}
				catch (const char * ErrorMsg)
				{
					std::cout << "Error! :" << ErrorMsg << std::endl;
					return false;
				}
				std::cout << MTL__FUNCTION_NAME__ << " Success" << std::endl;
				return true;
			}
			
		} // namespace THM1176Types
	} // namespace Instrument
} // namespace MTL
