#pragma once

#include <string>
using namespace std;

#define VAR_TYPE_INT				0
#define VAR_TYPE_SIGNED_INT			0
#define VAR_TYPE_UNSIGNED_INT		1

#define VAR_TYPE_CHAR				2
#define VAR_TYPE_SIGNED_CHAR		2
#define VAR_TYPE_UNSIGNED_CHAR		3
#define VAR_TYPE_BYTE				3	// == unsigned char

#define VAR_TYPE_SHORT				4
#define VAR_TYPE_SHORT_INT			4
#define VAR_TYPE_SIGNED_SHORT		4
#define VAR_TYPE_UNSIGNED_SHORT		5

#define VAR_TYPE_LONG				6
#define VAR_TYPE_LONG_INT			6
#define VAR_TYPE_SIGNED_LONG		6
#define VAR_TYPE_UNSIGNED_LONG		7

//#define VAR_TYPE_LONG_LONG			8	// 8바이트
//#define VAR_TYPE_UNSIGNED_LONG_LONG	9

#define VAR_TYPE_FLOAT				10	// 유효7자리. 10의 -38승 ~ 10의 38승
#define VAR_TYPE_DOUBLE				11	// 유효15자리. 10의 -308승 ~ 10의 308승
#define VAR_TYPE_LONG_DOUBLE		11

#define VAR_TYPE_LAST				11

#define VAR_TYPE_BRACE_BEGIN		20

typedef unsigned long long	ULLONG;



class LVariableItem
{
private:
	LVariableItem();

	string		m_strName;
	int			m_nType;
	long long	m_llValue;

public:
	LVariableItem(string strName, int nType);
	LVariableItem(string strName, int nType, long long llValue);
	LVariableItem(char *cpName, int nType, long long llValue = 0);
	LVariableItem(const LVariableItem& srcObject);

	LVariableItem& operator=(const LVariableItem& srcObject);

	bool				SetValue(void* pValue, int nVarType);
	bool				ValueToStr(string& strRef);
	long long			GetValue();
	string				GetName();
	int					GetType();
	
	/*
	int					GetIntValue();
	unsigned int		GetUnsignedIntValue();
	unsigned char		GetUnsignedCharValue();
	short				GetShortValue();
	unsigned short		GetUnsignedShortValue();
	long				GetLongValue();
	unsigned long		GetUnsignedLongValue();
	long long			GetLongLongValue();
	unsigned long long	GetUnsignedLongLongValue();
	float				GetFloatValue();
	double				GetDoubleValue();
	*/
};


LVariableItem::LVariableItem()
{

}
LVariableItem::LVariableItem(string strName, int nType)
{
	m_nType = nType;
	m_strName = strName;
}
LVariableItem::LVariableItem(string strName, int nType, long long llValue)
{
	m_nType = nType;
	m_strName = strName;
	m_llValue = llValue;
}
LVariableItem::LVariableItem(char *cpName, int nType, long long llValue)
{
	m_nType = nType;
	string newString(cpName);
	m_strName = newString;
	m_llValue = llValue;
}

LVariableItem::LVariableItem(const LVariableItem& srcObject)
{
	m_llValue = srcObject.m_llValue;
	m_strName = srcObject.m_strName;
	m_nType = srcObject.m_nType;
}

LVariableItem& LVariableItem::operator=(const LVariableItem& srcObject)
{
	m_llValue = srcObject.m_llValue;
	m_strName = srcObject.m_strName;
	m_nType = srcObject.m_nType;

	return *this;
}

bool LVariableItem::SetValue(void* pValue, int nVarType)
{
	if( nVarType != m_nType )
		return false;

	// TODO here : ★ short 과 같이 작은 크기 변수의 경우 long long 으로 저장하면
	// 잘리지 않고 잘 저장될 수 있으므로 캐스팅이 필요하겠다.

	switch( m_nType )
	{
	case VAR_TYPE_INT:
	case VAR_TYPE_LONG:
		m_llValue = *(long*)pValue;
		break;
	case VAR_TYPE_UNSIGNED_INT:
	case VAR_TYPE_UNSIGNED_LONG:
		m_llValue = *(unsigned long*)pValue;
		break;
	case VAR_TYPE_CHAR:
		m_llValue = *(char*)pValue;
		break;
	case VAR_TYPE_UNSIGNED_CHAR:
		m_llValue = *(unsigned char*)pValue;
		break;
	case VAR_TYPE_SHORT:
		m_llValue = *(short*)pValue;
		break;
	case VAR_TYPE_UNSIGNED_SHORT:
		m_llValue = *(unsigned short*)pValue;
		break;
	//case VAR_TYPE_LONG_LONG:
	//case VAR_TYPE_UNSIGNED_LONG_LONG:
	case VAR_TYPE_FLOAT:
		m_llValue = *(float*)pValue;
		break;
	case VAR_TYPE_DOUBLE:
		m_llValue = *(double*)pValue;
		break;
	default:
		return false;
		break;
	}
	return true;
}

bool LVariableItem::ValueToStr(string& strRef)
{
	char buf[30];
	memset( buf, 0x00, 30);

	switch( m_nType )
	{
	case VAR_TYPE_INT:
	case VAR_TYPE_LONG:
		itoa( (int)m_llValue, buf, 10 );
		break;
	case VAR_TYPE_CHAR:
		itoa( (char)m_llValue, buf, 10 );
		break;
	case VAR_TYPE_SHORT:
		itoa( (short)m_llValue, buf, 10 );
		break;
	case VAR_TYPE_UNSIGNED_INT:
	case VAR_TYPE_UNSIGNED_LONG:
		ultoa( (unsigned int)m_llValue, buf, 10 );
		break;
	case VAR_TYPE_UNSIGNED_CHAR:
		ultoa( (unsigned char)m_llValue, buf, 10 );
		break;
	case VAR_TYPE_UNSIGNED_SHORT:
		ultoa( (unsigned short)m_llValue, buf, 10 );
		break;
	//case VAR_TYPE_LONG_LONG:
	//	*((long long *)pValue) = (long long)m_llValue;
	//	break;
	//case VAR_TYPE_UNSIGNED_LONG_LONG:
	//	*((unsigned long long *)pValue) = (unsigned long long)m_llValue;
	//	break;
	case VAR_TYPE_FLOAT:
		gcvt( (float)m_llValue, 16, buf );
		break;
	case VAR_TYPE_DOUBLE:
		gcvt( (double)m_llValue, 16, buf );
		break;
	default:
		return false;
		break;
	}
	strRef = buf;
	return true;
}

long long LVariableItem::GetValue()
{
	return m_llValue;
}

string LVariableItem::GetName()
{
	return m_strName;
}

int LVariableItem::GetType()
{
	return m_nType;
}




/*
int LVariableItem::GetIntValue()
{
	if( m_nType == VAR_TYPE_INT )
		return (int)m_llValue;
	exit(-1);
	return 0;
}

unsigned int LVariableItem::GetUnsignedIntValue()
{
	if( m_nType == VAR_TYPE_UNSIGNED_INT )
		return (unsigned int)m_llValue;
	exit(-1);
	return 0;
}

unsigned char LVariableItem::GetUnsignedCharValue()
{
	if( m_nType == VAR_TYPE_UNSIGNED_CHAR )
		return (unsigned char)m_llValue;
	exit(-1);
	return 0;
}

short LVariableItem::GetShortValue()
{
	if( m_nType == VAR_TYPE_SHORT )
		return (short)m_llValue;
	exit(-1);
	return 0;
}

unsigned short LVariableItem::GetUnsignedShortValue()
{
	if( m_nType == VAR_TYPE_UNSIGNED_SHORT )
		return (unsigned short)m_llValue;
	exit(-1);
	return 0;
}

long LVariableItem::GetLongValue()
{
	if( m_nType == VAR_TYPE_LONG )
		return (long)m_llValue;
	exit(-1);
	return 0;
}

unsigned long LVariableItem::GetUnsignedLongValue()
{
	if( m_nType == VAR_TYPE_UNSIGNED_LONG )
		return (unsigned long)m_llValue;
	exit(-1);
	return 0;
}

long long LVariableItem::GetLongLongValue()
{
	if( m_nType == VAR_TYPE_LONG_LONG )
		return (long long)m_llValue;
	exit(-1);
	return 0;
}

unsigned long long LVariableItem::GetUnsignedLongLongValue()
{
	if( m_nType == VAR_TYPE_UNSIGNED_LONG_LONG )
		return (unsigned long long)m_llValue;
	exit(-1);
	return 0;
}

float LVariableItem::GetFloatValue()
{
	if( m_nType == VAR_TYPE_FLOAT )
		return (float)m_llValue;
	exit(-1);
	return 0;
}

double LVariableItem::GetDoubleValue()
{
	if( m_nType == VAR_TYPE_DOUBLE )
		return (double)m_llValue;
	exit(-1);
	return 0;
}

*/