//this file is part of NeoMule
//Copyright (C)2005 David Xanatos ( Xanatos@Lycos.at / http://NeoMule.tk )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "stdafx.h"
#include "UpDownCLient.h"
#include "Functions.h"
#include "MenuCmds.h"
#include "resource.h"
#include "Preferences.h"
#include "OtherFunctions.h"

int Str2Int(CString Buffer, int Min, int Def, int Max){
	int itemp = _tstol(Buffer);
	if (!itemp)
		itemp = Def;
	else
		if(Min && Max)
			MinMax (&itemp,Min,Max);
		else if(Min)
			Minimal (&itemp,Min);
	return itemp;
}
CString Int2Str(int Nummer) { 
	CString buffer=_T("0"); 
	buffer.Format(_T("%d"), Nummer); 
	return buffer; 
}

uint32 Str2UInt(CString Buffer, uint32 Min, uint32 Def, uint32 Max){
	uint32 itemp = _tstol(Buffer);
	if (!itemp)
		itemp = Def;
	else
		if(Min && Max)
			MinMax (&itemp,Min,Max);
		else if(Min)
			Minimal (&itemp,Min);
	return itemp;
}
CString UInt2Str(uint32 Nummer) { 
	CString buffer=_T("0"); 
	buffer.Format(_T("%u"), Nummer); 
	return buffer; 
}

float Str2FloatNum(CString Buffer, float Min, float Def, float Max){
	float ftemp = (float)_tstof(Buffer);
	if (!ftemp)
		ftemp = (float)Def;
	else
		if(Min && Max)
			MinMax (&ftemp,(float)Min,(float)Max);
		else if(Min)
			Minimal (&ftemp,(float)Min);
	return ftemp;
}
CString FloatNum2Str(float Nummer) { 
	CString buffer=_T("0.00"); 
	buffer.Format(_T("%.2f"),Nummer); 
	return buffer; 
}

uint32 MinStr2Time (CString Buffer, uint32 Min, uint32 Def, uint32 Max){
	double dtemp = _tstof(Buffer);
	uint32 itemp = (uint32)MIN2MS(dtemp);
	if (!dtemp)
		itemp = Def;
	else
		if(Min && Max)
			MinMax (&itemp,Min,Max);
		else if(Min)
			Minimal (&itemp,Min);
	return itemp;
}
CString Time2MinStr(uint32 Time) { 
	CString buffer=_T("0.00"); 
	buffer.Format(_T("%.2f"),MS2MIN((float)Time)); 
	return buffer; 
}

uint32 SecStr2Time (CString Buffer, uint32 Min, uint32 Def, uint32 Max){
	double dtemp = _tstof(Buffer);
	uint32 itemp = (uint32)SEC2MS(dtemp);
	if (!dtemp)
		itemp = Def;
	else
		if(Min && Max)
			MinMax (&itemp,Min,Max);
		else if(Min)
			Minimal (&itemp,Min);
	return itemp;
}
CString Time2SecStr(uint32 Time) { 
	CString buffer=_T("0.00"); 
	buffer.Format(_T("%.2f"),MS2SEC((float)Time)); 
	return buffer; 
}

CString StrLine(LPCTSTR line, ...)
{
	ASSERT(line != NULL);

	va_list argptr;
	va_start(argptr, line);
	const size_t bufferSize = 1000;
	TCHAR bufferline[bufferSize];	
	if (_vsnwprintf(bufferline, bufferSize, line, argptr) == -1)
		bufferline[bufferSize - 1] = _T('\0');
	va_end(argptr);	

	return bufferline;
}

CString Crypt(CString sNormal)
{
	ULONG lStringLen = sNormal.GetLength();
	BYTE *pBuf = new BYTE[lStringLen * 2 + 1];
	wcscpy((WCHAR *)pBuf, sNormal);

	for (ULONG dwBufSize = lStringLen; dwBufSize--; )
	{
		((PSTR) pBuf)[2 * dwBufSize + 1]	= (((PSTR) pBuf)[dwBufSize] % 0x10) + 'A';
		((PSTR) pBuf)[2 * dwBufSize]		= (((PSTR) pBuf)[dwBufSize] / 0x10) + 'A';
	}

	pBuf[lStringLen*2] = 0;

	CString str(pBuf);
	delete[] pBuf;

	return str;
}
CString Decrypt(CString sCrypted)
{
	ULONG lStringLen = sCrypted.GetLength();
	lStringLen /= 2;
	BYTE *pBuf = new BYTE[lStringLen + 1];

	for (ULONG dwPos = 0; dwPos < lStringLen; dwPos++)
	{
		TCHAR chHigh = ((PCTSTR) sCrypted)[dwPos * 2] - 'A';
		TCHAR chLow  = ((PCTSTR) sCrypted)[dwPos * 2 + 1] - 'A';

		((PSTR) pBuf)[dwPos] = (CHAR)((chHigh << 4) + chLow);
	}

	pBuf[lStringLen] = 0;

	CString str(pBuf);
	delete[] pBuf;

	return str;
}

CString DeCodeString(CString String)
{
	CString buffer = String;
	CString value = _T("");
	TCHAR nvalue[2] = {20,0};
	int num1 = 0;
	int num2 = 0;
	int findPos = 0;

	while ((findPos = buffer.Find(_T("%"))) > -1)
	{
		value = buffer.Mid(findPos, 3);
		swscanf(value,_T("%%%01X%01X"),&num1,&num2);
		nvalue[0]  = (TCHAR)num1 << 4;
		nvalue[0] |= (TCHAR)num2;
		buffer.Replace(value,nvalue);
	}

	return buffer;
}

CString ParseString(CString &strIn, int &nOffset, TCHAR what)
{
	CString strOut;
	int nLength = strIn.GetLength();

	if(nOffset < nLength)
	{
		if(strIn[nOffset] == what)
		{
			nOffset++;
			return strOut;
		}

		while(nOffset < nLength)
		{
			strOut += strIn[nOffset];
			if(strIn[++nOffset] == what)
				break;
		}

		strOut.Trim();
		nOffset++;
	}

	return strOut;
}

bool stristrex (const TCHAR *s1, const TCHAR *s2)
{
	TCHAR *cp = (TCHAR*) s1;
	TCHAR *s, *t;
	TCHAR l, r;

	while (*cp) {
		s = cp;
		t = (TCHAR*)s2;
		while (*s && *t) {
			l = ( (*s >= 'A') && (*s <= 'Z') ) ? 
				*s + 'a' - 'A' : *s;
			r = ( (*t >= 'A') && (*t <= 'Z') ) ? 
				*t + 'a' - 'A' : *t;
			if ( l != r)
				break;
			s++, t++;
		}

		if (*t == '\0')
			return true;

		cp++;
	}
	return false;
}

bool strcmpex (const TCHAR *s1, const TCHAR *s2)
{
	TCHAR *cp = (TCHAR*) s1;
	TCHAR *s, *t;
	TCHAR l, r;

	s = cp;
	t = (TCHAR*)s2;
	while (*s && *t) {
		l = ( (*s >= 'A') && (*s <= 'Z') ) ? 
			*s + 'a' - 'A' : *s;
		r = ( (*t >= 'A') && (*t <= 'Z') ) ? 
			*t + 'a' - 'A' : *t;
		if ( l != r)
			break;
		s++, t++;
	}

	if (*t == '\0')
		return true;

	return false;
}


// MOD: MTD - [MultiTempDirectories] -- Loulach -->

// MOD: MTD END <-- Loulach --

// MOD: NSC - [NeoSharedCategories] -- Loulach -->

// MOD: NSC END] <-- Loulach --

CString GetDLStateString(EDownloadState nState){
	CString strState;
	switch (nState)
	{
		case DS_CONNECTING:
			strState = GetResString(IDS_CONNECTING);
			break;
		case DS_CONNECTED:
			strState = GetResString(IDS_ASKING);
			break;
		case DS_CONNECTINGWAITING:
			strState = GetResString(IDS_X_CONNECTINGWAITING);
			break;
		// MOD: TCR - [TCPConnectionRetry]
		case DS_CONNECTIONRETRY:
			strState = GetResString(IDS_X_CONNECTIONRETRY);
			break;
		// MOD: TCR END
		case DS_WAITCALLBACK:
			strState = GetResString(IDS_CONNVIASERVER);
			break;
		case DS_ONQUEUE:
			strState = GetResString(IDS_ONQUEUE);
			break;
		case DS_REMOTEQUEUEFULL:
			strState = GetResString(IDS_QUEUEFULL);
			break;
		case DS_DOWNLOADING:
			strState = GetResString(IDS_TRANSFERRING);
			break;
		case DS_REQHASHSET:
			strState = GetResString(IDS_RECHASHSET);
			break;
		case DS_NONEEDEDPARTS:
			strState = GetResString(IDS_NONEEDEDPARTS);
			break;
		case DS_LOWTOLOWIP:
			strState = GetResString(IDS_NOCONNECTLOW2LOW);
			break;
		case DS_TOOMANYCONNS:
			strState = GetResString(IDS_TOOMANYCONNS);
			break;
		case DS_ERROR:
			strState = GetResString(IDS_ERROR);
			break;
		case DS_WAITCALLBACKKAD:
			strState = GetResString(IDS_KAD_WAITCBK);
			break;
		case DS_TOOMANYCONNSKAD:
			strState = GetResString(IDS_KAD_TOOMANDYKADLKPS);
			break;
	}

	return strState;
}

CString CastSecondsToDate(uint32 Secounds)
{
	time_t timer = Secounds;
	WCHAR* tmp = _wctime(&timer);
	CString ret = tmp ? tmp : _T("?");
	ret.Replace(_T("\n"),_T(""));
	return ret;
}

// Compares strings using wildcards * and ?.
int wildcmp(TCHAR *wild, TCHAR *string)
{
	TCHAR *cp = NULL;
	TCHAR *mp = NULL;

	while ((*string) && (*wild != '*'))
	{
		if ((*wild != *string) && (*wild != '?'))
			return 0;
		wild++;
		string++;
	}

	while (*string)
	{
		if (*wild == '*')
		{
			if (!*++wild)
				return 1;
			mp = wild;
			cp = string+1;
		}
		else if ((*wild == *string) || (*wild == '?'))
		{
			wild++;
			string++;
		}
		else
		{
			wild = mp;
			string = cp++;
		}
	}

	while (*wild == '*')
		wild++;
	return !*wild;
}

ULONG CastXBytesToI(const CString& strExpr)
{
	ULONG ulNum;
	TCHAR szUnit[40];
	int iArgs = _stscanf(strExpr, _T("%u%s"), &ulNum, szUnit);
	if (iArgs <= 0)
		return 0;
	if (iArgs == 2){
		CString strUnits(szUnit);
		strUnits.Trim();
		if (!strUnits.IsEmpty()){
			CString strBytes = GetResString(IDS_BYTES);
			if (strUnits.CompareNoCase(strBytes.Left(1)) == 0 || strUnits.CompareNoCase(strBytes) == 0)
				return ulNum * 1U; // Bytes
			else if (strUnits.CompareNoCase(_T("k")) == 0 || strUnits.CompareNoCase(GetResString(IDS_KBYTES)) == 0 || strUnits.CompareNoCase(_T("k")+strBytes) == 0)
				return ulNum * 1024U; // KBytes
			else if (strUnits.CompareNoCase(_T("m")) == 0 || strUnits.CompareNoCase(GetResString(IDS_MBYTES)) == 0 || strUnits.CompareNoCase(_T("m")+strBytes) == 0)
				return ulNum * 1024U*1024; // MBytes
			else if (strUnits.CompareNoCase(_T("g")) == 0 || strUnits.CompareNoCase(GetResString(IDS_GBYTES)) == 0 || strUnits.CompareNoCase(_T("g")+strBytes) == 0)
				return ulNum * 1024U*1024U*1024U; // GBytes
			else{
				AfxMessageBox(GetResString(IDS_SEARCH_EXPRERROR) + _T("\n\n") + GetResString(IDS_SEARCH_INVALIDMINMAX));
				return 0;
			}
		}
	}

	return ulNum * 1024U*1024U; // Default = MBytes
}

CString CastItoUIXBytes(uint64 count)
{
	CString buffer;
	if (count < 1024)
		buffer.Format(_T("%I64u%s"), count, GetResString(IDS_BYTES));
	else if (count < 1048576)
		buffer.Format(_T("%I64u%s"), (uint64)(count/1024), GetResString(IDS_KBYTES));
	else if (count < 1073741824)
		buffer.Format(_T("%I64u%s"), (uint64)(count/1048576), GetResString(IDS_MBYTES));
	else
		buffer.Format(_T("%I64u%s"), (uint64)(count/1073741824), GetResString(IDS_GBYTES));
	return buffer;
}

int CompareSubDirectories(const CString& rstrDir1, const CString& rstrDir2) // full file path // master directory
{
	if(rstrDir2.IsEmpty()) // for NSC
		return -3;

	if (CompareDirectories(rstrDir1,rstrDir2)==0)
		return 0;

	if(rstrDir1.GetLength() <= rstrDir2.GetLength())
		return -1;

	CString strDir2 = rstrDir2;
	if (strDir2.Right(1) == "\\")
		strDir2 = strDir2.Left(strDir2.GetLength()-1);

	if(strcmpex(rstrDir1,strDir2))
		return 0;
	else
		return -2;
}