#include <QString>
#include <stdint.h>
#include <math.h>
#include "dbNode.h"
#include <stdio.h>

//	----------------------------------------------------------------------------
//	dbNode
//	----------------------------------------------------------------------------

dbNode::dbNode()
{
	index = 0;
	iT = 0;
	iR = 0;
	iC = 0;
	iE = 0;
	type = 0;
	name = NULL;
	desc = NULL;
	list = NULL;
	precision = 0;
	listMax = 0;
	ptr = NULL;
	memset(vstring,0,sizeof(vstring));
}

//	----------------------------------------------------------------------------
//	init
//	----------------------------------------------------------------------------

int dbNode::init(
		int _index,
		int _iT,
		int _iR,
		int _iC,
		int _iE,
		int _type,
		const char *_name,
		const char *_desc,
		void *_ptr,
		const char **_list,
		int _precision
		)
{
	index = _index;
	iT = _iT;
	iR = _iR;
	iC = _iC;
	iE = _iE;
	type = _type;
	name = _name;
	desc = _desc;
	ptr = _ptr;
	list = _list;
	precision = _precision;
	if(list == NULL){
		listMax = 0;
	}else{
		for(int i=0;i<MAXDROP;i++){
			const char *s = list[i];
			int l = strlen(s);
			if(l>0){
				listMax = i;
			}else{
				break;
			}
		}
	}
	return 1;
}

//	----------------------------------------------------------------------------
//	nodeToStr
//	----------------------------------------------------------------------------

char *dbNode::nodeToStr()
{
	nodeToStr(vstring);
	return vstring;
}

//	----------------------------------------------------------------------------
//	isInteger
//	----------------------------------------------------------------------------

int dbNode::isInteger()
{
	switch(type){
		case D_int8_t:
		case D_int16_t:
		case D_int32_t:
		case D_int64_t:
		case D_uint8_t:
		case D_uint16_t:
		case D_uint32_t:
		case D_uint64_t:
			return 1;
		default:
			return 0;
	}
}

//	----------------------------------------------------------------------------
//	isList
//	----------------------------------------------------------------------------

int dbNode::isList()
{
	if(isInteger()){
		return (listMax>0)?(1):(0);
	}else{
		return 0;
	}
}

//	----------------------------------------------------------------------------
//	listString
//	----------------------------------------------------------------------------

int dbNode::listString(char *strPtr,int v)
{
	if((v<0)||(v>listMax)){
		sprintf(strPtr, "Invalid");
		return 0;
	}else{
		strcpy(strPtr,list[v]);
		return 1;
	}
}

//	----------------------------------------------------------------------------
//	nodeToFloat
//	----------------------------------------------------------------------------

float dbNode::nodeToFloat()
{
	if(ptr == NULL){
		return 0;
	}

	switch(type){

	case D_int8_t:{
		int8_t v = *(int8_t *)ptr;
		return (float)v;
		}

	case D_int16_t:{
		int16_t v = *(int16_t *)ptr;
		return (float)v;
		}

	case D_int32_t:{
		int32_t v = *(int32_t *)ptr;
		return (float)v;
		}

	case D_int64_t:{
		int64_t v = *(int64_t *)ptr;
		return (float)v;
		}

	case D_uint8_t:{
		uint8_t v = *(uint8_t *)ptr;
		return (float)v;
		}

	case D_uint16_t:{
		uint16_t v = *(uint16_t *)ptr;
		return (float)v;
		}

	case D_uint32_t:{
		uint32_t v = *(uint32_t *)ptr;
		return (float)v;
		}

	case D_uint64_t:{
		uint64_t v = *(uint64_t *)ptr;
		return (float)v;
		}

	case D_float:{
		float v = *(float *)ptr;
		return v;
		}

	case D_double:{
		double v = *(double *)ptr;
		return (float)v;
		}

	default:
		return 0;

	}
	return 0;
}
//	----------------------------------------------------------------------------
//	nodeToInt
//	----------------------------------------------------------------------------

int dbNode::nodeToInt()
{
	if(ptr == NULL){
		return 0;
	}

	switch(type){

	case D_int8_t:{
		int8_t v = *(int8_t *)ptr;
		return v;
		}

	case D_int16_t:{
		int16_t v = *(int16_t *)ptr;
		return v;
		}

	case D_int32_t:{
		int32_t v = *(int32_t *)ptr;
		return v;
		}

	case D_int64_t:{
		int64_t v = *(int64_t *)ptr;
		return v;
		}

	case D_uint8_t:{
		uint8_t v = *(uint8_t *)ptr;
		return v;
		}

	case D_uint16_t:{
		uint16_t v = *(uint16_t *)ptr;
		return v;
		}

	case D_uint32_t:{
		uint32_t v = *(uint32_t *)ptr;
		return v;
		}

	case D_uint64_t:{
		uint64_t v = *(uint64_t *)ptr;
		return v;
		}

	case D_float:{
		float v = *(float *)ptr;
		return (int)v;
		}

	case D_double:{
		double v = *(double *)ptr;
		return (int)v;
		}

	default:
		return 0;

	}
	return 0;
}

//	----------------------------------------------------------------------------
//	nodeToStr
//	----------------------------------------------------------------------------

int dbNode::nodeToStr(char *strPtr)
{
	int res = 0;

	if(ptr == NULL){
		sprintf(strPtr, "Invalid");
		return res;
	}

	switch(type){

	case D_int8_t:{
		int8_t v = *(int8_t *)ptr;
		if(listMax>0)return listString(strPtr,v);
		const char *intf = (precision==FM_HEX)?("%02X"):("%i");
		sprintf(strPtr,intf,v);
		res = 1;
		}
		break;

	case D_int16_t:{
		int16_t v = *(int16_t *)ptr;
		if(listMax>0)return listString(strPtr,v);
		const char *intf = (precision==FM_HEX)?("%04X"):("%i");
		sprintf(strPtr,intf,v);
		res = 1;
		}
		break;

	case D_int32_t:{
		int32_t v = *(int32_t *)ptr;
		if(listMax>0)return listString(strPtr,v);
		const char *intf = (precision==FM_HEX)?("%08X"):("%i");
		sprintf(strPtr,intf,v);
		res = 1;
		}
		break;

	case D_int64_t:{
		int64_t v = *(int64_t *)ptr;
		if(listMax>0)return listString(strPtr,v);
		const char *intf = (precision==FM_HEX)?("%08X"):("%lli");
		sprintf(strPtr,intf,v);
		res = 1;
		}
		break;

	case D_uint8_t:{
		uint8_t v = *(uint8_t *)ptr;
		if(listMax>0)return listString(strPtr,v);
		const char *intf = (precision==FM_HEX)?("%02X"):("%u");
		sprintf(strPtr,intf,v);
		res = 1;
		}
		break;

	case D_uint16_t:{
		uint16_t v = *(uint16_t *)ptr;
		if(listMax>0)return listString(strPtr,v);
		const char *intf = (precision==FM_HEX)?("%04X"):("%u");
		sprintf(strPtr,intf,v);
		res = 1;
		}
		break;

	case D_uint32_t:{
		uint32_t v = *(uint32_t *)ptr;
		if(listMax>0)return listString(strPtr,v);
		const char *intf = (precision==FM_HEX)?("%08X"):("%u");
		sprintf(strPtr,intf,v);
		res = 1;
		}
		break;

	case D_uint64_t:{
		uint64_t v = *(uint64_t *)ptr;
		if(listMax>0)return listString(strPtr,v);
		const char *intf = (precision==FM_HEX)?("%16X"):("%llu");
//		const char *intf = "%16hX";
		sprintf(strPtr,intf,v);
		res = 1;
		}
		break;

	case D_float:{
		float v;
		memcpy(&v,ptr,sizeof(v));
		if(qIsNaN(v)){
			sprintf(strPtr, "Invalid");
		}else{
			sprintf(strPtr,"%*.*f",5+precision,precision,v);
			res = 1;
		}}
		break;

	case D_float3:{
		float *v = (float *)ptr;
		char s[3][80];
		res = 1;
		for(int i = 0;i<3;i++){
			if(qIsNaN(v[i])){
				sprintf(strPtr, "Invalid");
				res = 0;
			}else{
				sprintf(s[i],"%*.*f",5+precision,precision,v[i]);
			}
		}
		sprintf(strPtr,"%s\t%s\t%s",s[0],s[1],s[2]);
		}
		break;


	case D_string:{
		int l = std::max(0,std::min((int)MAX_DB_STRING,precision));
		memcpy(strPtr,ptr,l);
		strPtr[l-1]=0;
		res = 1;
		}
		break;

	case D_double:{
		double v;
		memcpy(&v,ptr,sizeof(v));
		if(qIsNaN(v)){
			sprintf(strPtr, "Invalid");
		}else{
			float vv = (float)v;
			sprintf(strPtr,"%*.*f",5+precision,precision,vv);
			res = 1;
		}}
		break;

	case D_double3:{
		double *v = (double *)ptr;
		char s[3][80];
		res = 1;
		for(int i = 0;i<3;i++){
			if(qIsNaN(v[i])){
				sprintf(strPtr, "Invalid");
				res = 0;
			}else{
				float vv = (float)v[i];
				sprintf(s[i],"%*.*f",5+precision,precision,vv);
			}
		}
		sprintf(strPtr,"%s\t%s\t%s",s[0],s[1],s[2]);
		}
		break;

	default:
		sprintf(strPtr,"Invalid");
		break;

	}
	return res;
}
