#include "NTGlobals.h"
#include <stdarg.h>
#include "NTCurses.h"
#include <cstdlib>
#include <string.h>
#include <strings.h>

#ifdef WIN32
#include <windows.h>
#include <math.h>
LARGE_INTEGER micro_log_startuptime;
int micro_log_freq = 0;
#else
#include <sys/time.h>
struct timeval micro_log_startuptime;
int micro_log_freq = 0;
#endif


namespace NT {

NTString::NTString() : std::string() { }
NTString::NTString( const char *str ) : std::string( str ) { }
NTString::NTString( std::string str ) : std::string( str ) { }

void vstrprintf( NTString &str , const char *fmt , va_list args ) {
	char tempstring[256*1024];
	vsnprintf( tempstring  , 256*1024 , fmt , args );
	str = tempstring;
}

NTString format_string( const char *fmt , ... ) {
	NTString retval;
	va_list args;
	va_start( args , fmt );
	vstrprintf( retval , fmt , args );
	va_end( args );
	return retval;
}

NTString addslashes( NTString str ) {
	NTString retval="";
	unsigned int i;
	unsigned int len = str.length();
	unsigned char ch;
	for (i=0;i<len;i++) {
		ch = str.at(i);
		switch (ch) {
		case '\'':
			retval+="''";
			break;
		default:
			retval+=ch;
		}
	}
	return retval;
}

NTString center_pad_string( NTString str , unsigned int maxlength ) {
	NTString retval;
	unsigned int i,len;
	len = str.length();
	if (maxlength<len) return str;

	unsigned int p = (maxlength-len)/2;

	retval = "";
	for (i=0;i<p;i++) retval+=" ";
	retval+=str;
	i+=len;
	while (i<maxlength) {
		retval+=" ";
		i++;
	}
	return retval;
}

NTString pad_string( NTString str , unsigned int maxlength , bool cut ) {
	NTString retval;

	if (cut) {
		retval = str.substr( 0 , maxlength );
		unsigned int len;
		len = retval.length();
		while (len<maxlength) {
			retval+=" ";
			len++;
		}
	}
	return retval;
}

NTString reduce_spaces( NTString str ) {
	NTString retval;
	retval = str;
	std::string::size_type loc;
	loc = retval.find( "  " );
	while (loc!=std::string::npos ) {
		retval.erase( loc , 1 );
		loc = retval.find( "  " );
	}
	return retval;
}

NTString strtolower( NTString str ) {
	// FIXME xlat table
	NTString retval;
	unsigned int len = str.length();
	for (unsigned int i=0;i<len;i++) {
		unsigned char ch = str.at(i);
		switch (ch) {
		case 0xc1:ch='á';break;
		case 0xcd:ch='í';break;
		case 0xdb:ch='û';break;
		case 0xd5:ch='õ';break;
		case 0xdc:ch='ü';break;
		case 0xd6:ch='ö';break;
		case 0xda:ch='ú';break;
		case 0xd3:ch='ó';break;
		case 0xc9:ch='é';break;
		default:
			ch = tolower(ch);
		}
		retval+=ch;
	}
	return retval;
}

NTString convert_path_slashes( NTString str ) {
	NTString retval = "";
	unsigned int len=str.length();
	for (unsigned int i=0;i<len;i++) {
		unsigned char ch = str.at(i);
		switch (ch) {
#ifdef WIN32
		case '/':retval+='\\';break;
#else
		case '\\':retval+='/';break;
#endif
		default:
			retval+=ch;
		}
	}
	return retval;
}

bool is_valid_date( NTString d ) {
	if (d.length()!=10) return false;

	int year = atoi( d.substr( 0 , 4 ).c_str() );
	int month = atoi( d.substr( 5 , 2 ).c_str() );
	int day = atoi( d.substr( 8 , 2 ).c_str() );

	struct tm mytm,mytm2;
	memset( &mytm , 0 , sizeof( struct tm ) );
	mytm.tm_year = year-1900;
	mytm.tm_mon = month-1;
	mytm.tm_mday = day;
	mytm2 = mytm;

	mktime( &mytm );
	if (mytm.tm_year!=mytm2.tm_year) return false;
	if (mytm.tm_mon!=mytm2.tm_mon) return false;
	if (mytm.tm_mday!=mytm2.tm_mday) return false;
	return true;
}

NTString trim_string( NTString str ) {
	NTString retval;
	std::string::size_type first=str.find_first_not_of( " \t\r\n" );
	std::string::size_type last=str.find_last_not_of( " \t\r\n" );
	if (first==std::string::npos) return "";
	if (last==std::string::npos) return "";
	retval = str.substr( first , last-first+1 );
	return retval;
}

std::vector<NTString> explode( NTString sep , NTString str ) {
	std::vector<NTString> retval;
	std::string::size_type loc;
	loc = str.find( sep );
	while (loc!=std::string::npos) {
		retval.push_back( str.substr( 0 , loc ) );
		str.erase( 0 , loc + sep.length() );
		loc = str.find( sep );
	}
	if (str.length())
		retval.push_back( str );
	return retval;
}

NTString implode( NTString sep , std::vector<NTString> arr ) {
	unsigned int len = arr.size();
	if (!len) return "";
	NTString retval="";
	bool first = true;
	unsigned int i=0;
	for (i=0;i<len;i++) {
		if (!first) retval+=sep;
		retval+=arr.at(i);
		first=false;
	}
	return retval;
}

unsigned int vline_replacer( unsigned int ch ) {
	switch (ch) {
	case '|':
		ch = ACS_VLINE;
		break;
	}
	return ch;
}



void micro_log( const char *string ) {
#if 0
#ifdef WIN32
	if (!micro_log_freq) {
		LARGE_INTEGER f;
		QueryPerformanceFrequency( &f );
		micro_log_freq = f.LowPart;
		QueryPerformanceCounter( &micro_log_startuptime );
	}
	LARGE_INTEGER now,diff;
	QueryPerformanceCounter( &now );
	diff.HighPart=now.HighPart-micro_log_startuptime.HighPart;
	if (now.LowPart>=micro_log_startuptime.LowPart) {
		diff.LowPart=now.LowPart-micro_log_startuptime.LowPart;
	} else {
		diff.HighPart--;
		diff.LowPart=micro_log_freq+now.LowPart-micro_log_startuptime.LowPart;
	}
	fprintf( stderr , "%10d microsecs %s\n",
		(int)floor((double)diff.LowPart*1000000.0/(double)micro_log_freq),
		string );
	QueryPerformanceCounter( &micro_log_startuptime );
#else
	if (!micro_log_freq) {
		gettimeofday( &micro_log_startuptime , NULL );
		micro_log_freq=1000000;
	}
	struct timeval now,diff;
	gettimeofday( &now , NULL );
	diff.tv_sec = now.tv_sec - micro_log_startuptime.tv_sec;
	if (now.tv_usec>=micro_log_startuptime.tv_usec) {
		diff.tv_usec = now.tv_usec - micro_log_startuptime.tv_usec;
	} else {
		diff.tv_sec--;
		diff.tv_usec = 1000000 + now.tv_usec - micro_log_startuptime.tv_usec;
	}
	fprintf( stderr , "%10ld microsecs %s\n",
		diff.tv_sec*1000000+diff.tv_usec,string );
	gettimeofday( &micro_log_startuptime , NULL );
#endif
#endif

}

unsigned int XlatChar( unsigned int ch , int from , int to ) {
	if (!from) from=28592;
#ifdef WIN32
	if (!to) to=852;
#else
	if (!to) to=28592;
#endif
	if (from==to) return ch;
#define xlat(a,b) case a:retval=b;break
	unsigned int retval=0;
	unsigned char chc=ch;
	if (from==28592 && to==852) {
		// latin2 to WINDOWS OEM
		switch (chc) {
		xlat(0xc1,0xb5);	// Á
		xlat(0xcd,0xd6);	// í
		xlat(0xdb,0xeb);	// Û
		xlat(0xd5,0x8a);	// Õ
		xlat(0xdc,0x9a);	// Ü
		xlat(0xd6,0x99);	// Ö
		xlat(0xda,0xe9);	// Ú
		xlat(0xd3,0xe0);	// Ó
		xlat(0xc9,0x90);	// É
		xlat(0xe1,0xa0);	// á
		xlat(0xed,0xa1);	// í
		xlat(0xfb,0xfb);	// û
		xlat(0xf5,0x8b);	// õ
		xlat(0xfc,0x81);	// ü
		xlat(0xf6,0x94);	// ö
		xlat(0xfa,0xa3);	// ú
		xlat(0xf3,0xa2);	// ó
		xlat(0xe9,0x82);	// é
		default:
			retval=ch;
		}
	} else if (from==852 && to==28592) {
		switch (chc) {
		xlat(0x8f,0xc1);	// Á pontos
		xlat(0xb5,0xc1);	// Á
		xlat(0xd6,0xcd);	// í
		xlat(0xeb,0xdb);	// Û
		xlat(0x8a,0xd5);	// Õ
		xlat(0x9a,0xdc);	// Ü
		xlat(0x99,0xd6);	// Ö
		xlat(0xe9,0xda);	// Ú
		xlat(0xe0,0xd3);	// Ó
		xlat(0x90,0xc9);	// É
		xlat(0xa0,0xe1);	// á
		xlat(0xa1,0xed);	// í
		xlat(0xfb,0xfb);	// û
		xlat(0x8b,0xf5);	// õ
		xlat(0x81,0xfc);	// ü
		xlat(0x94,0xf6);	// ö
		xlat(0xa3,0xfa);	// ú
		xlat(0xa2,0xf3);	// ó
		xlat(0x82,0xe9);	// é
		default:
			retval=ch;
		}
	}
#undef xlat
	return retval;
}

}
