/***************************************************************************
 ** $Id: functions.cpp,v 1.14 2008/07/31 19:56:26 hoganrobert Exp $
 *   Copyright (C) 2006 - 2008 Robert Hogan                                *
 *   robert@roberthogan.net                                                *
 *   Copyright (C) 2005 by Joris Guisson                                   *
 *   joris.guisson@gmail.com                                               *
 *                                                                         *
 *   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.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
 ***************************************************************************/
 
#include <tqdatetime.h>
#include <tqdir.h>

#include <tdelocale.h>
#include <tdeglobal.h>
#include <kdebug.h>

#include <sys/time.h>
#include <cstdlib>

#include "functions.h"


namespace tk
{
	const double TO_KB = 1024.0;
	const double TO_MEG = (1024.0 * 1024.0);
	const double TO_GIG = (1024.0 * 1024.0 * 1024.0);
	
	TQString BytesToString(Uint64 bytes,int precision)
	{
		TDELocale* loc = TDEGlobal::locale();
		if (bytes >= 1024 * 1024 * 1024)
			return i18n("%1 GB").arg(loc->formatNumber(bytes / TO_GIG,precision < 0 ? 2 : precision));
		else if (bytes >= 1024*1024)
			return i18n("%1 MB").arg(loc->formatNumber(bytes / TO_MEG,precision < 0 ? 1 : precision));
		else if (bytes >= 1024)
			return i18n("%1 KB").arg(loc->formatNumber(bytes / TO_KB,precision < 0 ? 1 : precision));
		else
			return i18n("%1 B").arg(bytes);
	}

	TQString BytesPerSecToString(double bytes,int precision)
	{
		TDELocale* loc = TDEGlobal::locale();
		if (bytes >= 1024 * 1024 * 1024)
			return i18n("%1 GB/s").arg(loc->formatNumber(bytes / TO_GIG,precision < 0 ? 2 : precision));
		else if (bytes >= 1024*1024)
			return i18n("%1 MB/s").arg(loc->formatNumber(bytes / TO_MEG,precision < 0 ? 1 : precision));
		else if (bytes >= 1024)
			return i18n("%1 KB/s").arg(loc->formatNumber(bytes / TO_KB,precision < 0 ? 1 : precision));
		else
			return i18n("%1 B/s").arg(loc->formatNumber(bytes,precision < 0 ? 1 : precision));
	}

	TQString KBytesPerSecToString(double speed,int precision)
	{
		TDELocale* loc = TDEGlobal::locale();
		return i18n("%1 KB/s").arg(loc->formatNumber(speed,precision));
	}


	TQString DurationToString(Uint32 nsecs)
	{
		TDELocale* loc = TDEGlobal::locale();
		TQTime t;
		int ndays = nsecs / 86400;
		t = t.addSecs(nsecs % 86400);
		TQString s = loc->formatTime(t,true,true);
		if (ndays > 0)
			s = i18n("1 day ","%n days ",ndays) + s;

		return s;
	}

    TQString calcBW(const TQStringList &bwlist, int num)
    {

        double totalbw = 0;
        int numtmp=0;
        for ( TQStringList::ConstIterator it = bwlist.end(); it != bwlist.begin(); --it )
        {
            totalbw += (*it).toDouble();
            numtmp++;
            if (numtmp > num)
              break;
        }
        double avgbw = totalbw / (900 * num);
        return BytesPerSecToString(avgbw);
    }

}

namespace bt
{

	void UpdateCurrentTime()
	{
		global_time_stamp = Now();
	}
	
	TimeStamp global_time_stamp = 0;
	
	Uint64 Now()
	{
		struct timeval tv;
		gettimeofday(&tv,0);
		global_time_stamp = (Uint64)(tv.tv_sec * 1000 + tv.tv_usec * 0.001);
		return global_time_stamp;
	}

}


TQString getFullLocation(const char *additionalPaths, const TQString &name)
{

    // do not search one path twice
    TQStringList paths;
    // get the environment path variable
    paths = addPaths(getenv("PATH"));
    paths += addPaths(additionalPaths);

	TQStringList::ConstIterator dirpath = paths.begin();
	TQStringList::ConstIterator end = paths.end();
	for(; dirpath!=end; ++dirpath)
	{
		TQDir dir = *dirpath;
		if (!dir.exists()) continue;

        TQFile inf(*dirpath+'/'+name);
        if (inf.exists())
            return *dirpath+'/'+name;

	}
    return TQString();
}


TQStringList findPrograms(const TQStringList &programList)
{

    // do not search one path twice
    TQStringList paths;
    // get the environment path variable
    paths = addPaths(getenv("PATH"));
    TQStringList tofind;
    TQStringList remaining;
    TQStringList finds;
	TQStringList::ConstIterator dirpath = paths.begin();
	TQStringList::ConstIterator end = paths.end();

    tofind = programList;
    remaining = tofind;
	for(; dirpath!=end; ++dirpath)
	{
		TQDir dir = *dirpath;
		if (!dir.exists()) continue;

    	for ( TQStringList::Iterator it = tofind.begin(); it != tofind.end(); ++it ){
            TQFile inf(*dirpath+'/'+*it);
            if (inf.exists()){
                finds.append(*it);
                remaining.remove(*it);
            }
		}
        tofind = remaining;
	}

    return finds;
}


TQStringList addPaths(const char *env_path){

    // do not search one path twice
    TQStringList paths;
/*    // get the environment path variable
    char* env_path = getenv("PATH");*/
    if( env_path ) {
      TQStringList env_pathList = TQStringList::split(":", TQString::fromLocal8Bit(env_path));
      for( TQStringList::const_iterator it = env_pathList.begin(); it != env_pathList.end(); ++it ) {
        TQString p = *it;
        if( p[p.length()-1] == '/' )
      p.truncate( p.length()-1 );
        if( !paths.contains( p ) && !paths.contains( p + "/" ) )
      paths.append(p);
      }
    }

    return paths;
}
