/***************************************************************************
                          cutils.cpp  -  description
                             -------------------
    begin                : Fri May 16 2003
    copyright            : (C) 2003-2005 by Mathias Küster
    email                : mathen@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "cutils.h"

#include "chttp.h"

/** */
CUtils::CUtils()
{
}

/** */
CUtils::~CUtils()
{
}

/** */
CString CUtils::GetSizeString( const ulonglong size, eUnit unit )
{
	CString s, suffix;
	double f;

	if ( (size > (1.0*1024*1024*1024*1024)) && (unit == euAUTO) )
	{
		suffix = " TiB";
#ifndef WIN32
		f = (size*1.0)/(1.0*1024*1024*1024*1024);
#else
		f = ((longlong)size*1.0)/(1.0*1024*1024*1024*1024);
#endif
	}
	else if ( ((size > (1024*1024*1024)) && (unit == euAUTO)) || (unit == euGBYTE) )
	{
		suffix = " GiB";
#ifndef WIN32
		f = (size*1.0)/(1024*1024*1024);
#else
		f = ((longlong)size*1.0)/(1024*1024*1024);
#endif
	}
	else if ( ((size > (1024*1024)) && (unit == euAUTO)) || (unit == euMBYTE) )
	{
		suffix = " MiB";
#ifndef WIN32
		f = (size*1.0)/(1024*1024);
#else
		f = ((longlong)size*1.0)/(1024*1024);
#endif
	}
	else if ( ((size > 1024) && (unit == euAUTO)) || (unit == euKBYTE) )
	{
		suffix = " KiB";
#ifndef WIN32
		f = (size*1.0)/1024;
#else
		f = ((longlong)size*1.0)/1024;
#endif
	}
	else if  ( (unit == euAUTO) || (unit == euBYTE) )
	{
		suffix = " B";
		f = 0;
	}
	else
	{
		f = 0;
	}

	if ( f != 0 )
	{
		s = CString::number(f,2);
	}
	else
	{
		s = CString::number(size);
	}

	s += suffix;

	return s;
}


/* This will Convert Total Secs to how much time is
 * remaining X Days + X Hrs + X Mins + X Secs */
CString CUtils::GetTimeString( const ulonglong sec )
{
	CString s;
	CString r = " S";
	ulonglong rate = sec;

	if ( rate >= (60*60*24) )
	{
		s += CString::number(rate/(60*60*24));
		s += " D ";
		rate %= (60*60*24);
	}
	if ( rate >= (60*60) )
	{
		s+= CString::number(rate/(60*60)).RightJustify(2,'0');
		s+=':';
		rate %= (60*60);
	}
	else
	{
		s+= "00:";
	}

	if ( rate >= 60 )
	{
		s += CString::number(rate/60).RightJustify(2,'0');
		s += ':';
		rate %= 60;
	}
	else
	{
		s+= "00:";
	}

	s += CString::number(rate).RightJustify(2,'0');

	return s;
}

/** */
CString CUtils::GetTransferString( const ulonglong rate )
{
	CString s;
	double f;

	if ( rate >= (1024*1024) )
	{
		s = " MiB/s";
		f = (rate*1.0)/(1024*1024);
	}
	else if ( rate >= 1024 )
	{
		s  = " KiB/s";
		f = (rate*1.0)/(1024);
	}
	else
	{
		s = " B/s";
		f = (rate*1.0);
	}

	return CString::number(f,2) + s;
}

/** */
bool CUtils::ConvertDCLink( CString link, CString & hubhost, CString & hubname, CString & nick, ulonglong & size, CString & file, CString & tth )
{
	bool res = false;
	long i,i1;
	CString s;
	CString tag;

	//printf("'%s'\n",link.Data());

	if ( link.FindCase("DCFILE://") != 0 )
	{
		return res;
	}

	link = link.Right( link.Length()-9 );

	if ( (i=link.Find('?')) == -1 )
	{
		return res;
	}

	hubhost = link.Left(i);
	link = "&" + link.Right( link.Length()-i-1 );

	while( link.NotEmpty() )
	{
		i1 = link.Find('&');
		i  = link.Find('&',i1+1);
		
		if ( i1 == -1 )
		{
			break;
		}
		 
		if ( i == -1 )
		{
			i = link.Length();
		}
		
		s = link.Left(i);
		link = link.Right( link.Length()-i );

		if ( s.FindCase("&FILE=") == 0 )
			file = CHttp::Decode(s.Right( s.Length()-6 ));
		else if ( s.FindCase("&NICK=") == 0 )
			nick = CHttp::Decode(s.Right( s.Length()-6 ));
		else if ( s.FindCase("&HUB=") == 0 )
			hubname = CHttp::Decode(s.Right( s.Length()-5 ));
		else if ( s.FindCase("&SIZE=") == 0 )
			size = CHttp::Decode(s.Right( s.Length()-6 )).asULL();
		else if ( s.FindCase("&HASH=") == 0 )
		{
			tth = s.Right( s.Length()-6 );
			if ( tth.Left(4).ToUpper() == "TTH:" )
			{
				tth = tth.Mid(4);
			}
		}
	}

	//printf("'%s'\n",hubhost.Data());
	//printf("'%s'\n",hubname.Data());
	//printf("'%s'\n",nick.Data());
	//printf("'%lld'\n",size);
	//printf("'%s'\n",file.Data());

	if ( (hubhost.NotEmpty()) &&
	     (hubname.NotEmpty()) &&
	     (nick.NotEmpty()) &&
	     (file.NotEmpty()) )
	{
		res = true;
	}

	return res;
}

/** */
bool CUtils::ParseVersionTag( const CString tag, int & major, int & minor, int & micro )
{
	int start = tag.Find("V:");
	
	if ( start == -1 )
	{
		return false;
	}
	
	start += 2; // length of "V:"
	
	int end = tag.Find(',',start);
	
	if ( end == -1 )
	{
		return false;
	}
	
	CString ver = tag.Mid(start,end-start);
	
	//printf("start=%d end=%d ver=\"%s\"\n", start, end, ver.Data());
	
	ver.Append('.');
	
	CString first = ver.Section('.',0,0);
	CString second = ver.Section('.',1,1);
	CString third = ver.Section('.',2,2);
	
	//printf("first=%s second=%s third=%s\n", first.Data(), second.Data(), third.Data());
	
	bool res = false;
	
	int i = first.asINT();
	
	/* 0.3.22svn should parse to 0 3 22 */
	if ( first.StartsWith(CString::number(i)) )
	{
		res = true;
		major = i;
	}
	else
	{
		return false;
	}
	
	i = second.asINT();
	
	if ( second.StartsWith(CString::number(i)) )
	{
		minor = i;
	}
	else if ( res )
	{
		minor = 0;
	}
	
	i = third.asINT();
	
	if ( third.StartsWith(CString::number(i)) )
	{
		micro = i;
	}
	else if ( res )
	{
		micro = 0;
	}

	return res;
}
