/***************************************************************************
 ** $Id: torkview.h,v 1.59 2009/10/20 20:16:00 hoganrobert Exp $
 *   Copyright (C) 2006 - 2008 Robert Hogan                                *
 *   robert@roberthogan.net                                                *
 *                                                                         *
 *   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.              *
 ***************************************************************************/


#ifndef _TORKVIEW_H_
#define _TORKVIEW_H_

#include <tqwidget.h>
#include <tqlistview.h>
#include <tqdragobject.h>
#include <tqiconview.h>
#include <tqdatetime.h>

#include <kpassivepopup.h>

#include "newstreamosd.h"
#include "torkview_base.h"
#include "hitwidget.h"
#include "kwidgetlistbox.h"
#include "kerrylabel.h"
#include "dndlistview.h"


class TQPainter;
class KURL;
class TQListViewItem;
class TQDragEnterEvent;
class TQDragDropEvent;
class KPassivePopup;
class StreamOSD;
class HitWidget;
class streamItem;

/**
 * This is the main view class for tork.  Most of the non-menu,
 * non-toolbar, and non-statusbar (e.g., non frame) GUI code should go
 * here.
 *
 * @short Main view
 * @author Robert Hogan <robert@roberthogan.net>
 * @version 0.1
 */
class torkView : public torkview_base
{
    TQ_OBJECT

	enum {
		HISTORY_SIZE = 300,	// Speed history buffer size
		SPEED_BUFFER_SIZE = 10	// Speed normalization buffer size
	};

public:
	/**
	 * Default constructor
	 */
    torkView(TQWidget *parent);

	/**
	 * Destructor
	 */
    virtual ~torkView();

    void hidePopup();
    bool getShowTormon() {return m_tormon;}
    void setShowTormon(bool tormon) { m_tormon = tormon;}
    void infoUpdated(const TQString &type, const TQString &summary,
                     const TQString &data);
    TQStringList subnet16List(){ return m_subnet16List; }
    TQValueList<int> countryList(){ return m_countryList; }
    StreamOSD* m_osd;
    StreamOSD* m_nontorosd;
    void toggleAnonymizerTork(bool state);
    HitWidget* welcomeitem;
    HitWidget* hiddenservicesitem;
    HitWidget* mixminionitem;
    HitWidget* sshitem;
    HitWidget* kopeteitem;
    HitWidget* gaimitem;
    HitWidget* pidginitem;
    HitWidget* konversationitem;
    HitWidget* gpgitem;
    HitWidget* konqitem;
    HitWidget* telnetitem;
    HitWidget* allpurposeitem;
    HitWidget* ksircitem;
    HitWidget* operaitem;
    HitWidget* firefoxitem;
    TQValueList<HitWidget*> menuItems;

    KURLLabel *configurePriv;
    KURLLabel *configurePrivText;

	//	Rx e Tx to bytes and packets
	unsigned long mBRx, mBTx, sysmBRx,sysmBTx;
	// Statistics
	unsigned long mTotalBytesRx, mTotalBytesTx;
	// Speed buffers
	double mSpeedBufferRx[SPEED_BUFFER_SIZE],
           mSpeedBufferTx[SPEED_BUFFER_SIZE];
    double sys_mSpeedBufferRx[SPEED_BUFFER_SIZE],
           sys_mSpeedBufferTx[SPEED_BUFFER_SIZE];
	// pointer to current speed buffer position
	int mSpeedBufferPtr;
    int sys_mSpeedBufferPtr;

	// History buffer TODO: Make it configurable!
	double mSpeedHistoryRx[HISTORY_SIZE];
	double mSpeedHistoryTx[HISTORY_SIZE];
	double sys_mSpeedHistoryRx[HISTORY_SIZE];
	double sys_mSpeedHistoryTx[HISTORY_SIZE];

	int mSpeedHistoryPtr;
	double mMaxSpeed;
	int mMaxSpeedAge;
	int sys_mSpeedHistoryPtr;
	double sys_mMaxSpeed;
	int sys_mMaxSpeedAge;

	const double* speedHistoryRx() const { return mSpeedHistoryRx; }
	const double* speedHistoryTx() const { return mSpeedHistoryTx; }
	int historyBufferSize() const { return HISTORY_SIZE; }
	const int* historyPointer() const { return &mSpeedHistoryPtr; }
	const double* maxSpeed() const { return &mMaxSpeed; }

	const double* sys_speedHistoryRx()
                  const { return sys_mSpeedHistoryRx; }
	const double* sys_speedHistoryTx()
                  const { return sys_mSpeedHistoryTx; }
	int sys_historyBufferSize() const { return HISTORY_SIZE; }
	const int* sys_historyPointer()
                  const { return &sys_mSpeedHistoryPtr; }
	const double* sys_maxSpeed() const { return &sys_mMaxSpeed; }

	// calc tha max. speed stored in the history buffer
	inline void calcMaxSpeed();
	inline void sys_calcMaxSpeed();
	// calc the speed using a speed buffer
	inline double calcSpeed(const double* buffer) const;

	/// RX Speed in bytes per second
	inline double byteSpeedRx() const;
	/// TX Speed in bytes per second
	inline double byteSpeedTx() const;

	/// RX Speed in bytes per second
	inline double sys_byteSpeedRx() const;
	/// TX Speed in bytes per second
	inline double sys_byteSpeedTx() const;

	static inline TQString byteFormat( double num,
                                      const char* ksufix = " KB",
                                      const char* msufix = " MB");

    void resetBWHistory();
    void updateChart();
    TQStringList m_subnet16List;
    TQValueList<int> m_countryList;
    void clearStreamMaps();

    TQTime timeLastTorUse;
    TQTime timeTorWasLastUsed(){return timeLastTorUse;};
    TQString addrLastTorUse;
    TQString addrTorWasLastUsed(){return addrLastTorUse;};

    void setGeoIPAvailable(bool set){geoip_db = set;};

signals:

    /**
     * Use this signal to change the content of the caption
     */
    void signalChangeCaption(const TQString& text);
    void showSecurityNotice(const TQString& cleanedPort);
    void showScreamingNotice(const TQString& cleanedPort);
    void showMyKonqueror();
    void riskySession();
    void aboutTorify();
    void aboutTor();
    void configurePrivoxy();
    void aboutParanoidMode();
    void showMyHiddenServices();
    void startEverything();
    void stopEverything();
    void updateStats();
    void mixminionHome();
    void processWarning(const TQString& , const TQString& );
    void signalCheckGuards();
    void signalCheckTorNet();
    void signalCheckBWSettings();
    void updateTrayStats(const TQString &,const TQString &,
                         const TQString &,const TQString &);

public slots:
    void toggleParanoidMode(int);
    void torify(const TQString &);
    void sendAnonymousEmail();
    void anonymousOpera();
    void anonymousFirefox();
    void anonymizedOpera(const TQString &);
    void anonymizedFirefox(const TQString &);
    void showServerBW(const TQString&);
private slots:
    void switchColors();
    void settingsChanged();
    void streamStatusUpdated(const TQString &, const TQString &,
                             const TQString &, const TQString &,
                             const TQString &);
    void circuitStatusUpdated(const TQString &, const TQString &,
                              const TQString &, const TQString &);
    void ORStatusUpdated(const TQString &ORID, const TQString &status);
    void guardStatusUpdated(const TQString &ORID, const TQString &status);
    void bwUpdated(const TQString &in, const TQString &out);
    void streamBwUpdated(const TQString &stream, const TQString &in,
                         const TQString &out);
    TQPixmap streamProgram(const TQString &port);
    void activeServersUpdated(const TQStringList &servers);
    void displayError(const TQString &,const TQString &);
    void displayServer(const TQString &,const TQString &);
    void serverStatusUpdated(const TQString &, const TQString &,
                             const TQString &,const TQString &);
    void privoxiedBash();
    void downloadMixminion();
    void downloadTorButton();
    void reportBW(int secs);
    void changeQuickConfigure(int no);

private:

    unsigned long readInterfaceNumValue(TQString interface,
                                        const char* name);
    void setHiddenServicesText();
    TQString parseStreamPort(const TQString &);
    void populateMenu();

    bool geoip_db;

    KPassivePopup* m_pop;
    bool m_tormon;
    TQStringList mSysDevPathList;
    bool mFirstUpdate;
    bool checkInterface();
    bool gotEth0;
    KURLLabel *paranoidmodeicon;
    KURLLabel *paranoidmodetext;
    TQStringList greenonion;
    TQStringList redonion;
    TQStringList yellowonion;
    TQStringList orangeonion;
    TQStringList littleonion;
    TQStringList todelete;
    TQValueList<TQStringList> iconList;
    TQValueList<TQString> torType;


    TQStringList guard;
    TQStringList redguard;
    TQStringList detachedguard;
    TQStringList littleguard;
    TQValueList<TQStringList> guardIconList;
    TQValueList<TQStringList> circuitIconList;

    typedef TQMap<TQString, TQString> stringmap;
    stringmap entryGuards;
    stringmap streamPurpose;
    stringmap portStream;

    typedef TQMap<TQString, streamItem*> streamlist;
    streamlist streams;
    typedef TQMap<TQString, TQListViewItem*> osdstreamlist;
    osdstreamlist osdstreams;
    osdstreamlist logstreams;
    osdstreamlist torservers;
    osdstreamlist circuitExits;
    typedef TQMap<TQString, TQPixmap> stringToPixmap;
    stringToPixmap streamStatusIcon;
    stringToPixmap cachedStreamIcon;

    typedef TQMap<TQString, int> streamBw;
    streamBw streamBwIn;
    streamBw streamBwOut;


    TQLabel *welcomeheaderLabel;

    unsigned int torbtx;
    unsigned int torbrx;
    unsigned int progDisplayCounter;
};

void torkView::calcMaxSpeed() {
	double max = 0.0;
	int ptr = mSpeedHistoryPtr;
	for (int i = 0; i < HISTORY_SIZE; ++i) {
		if (mSpeedHistoryRx[i] > max) {
			max = mSpeedHistoryRx[i];
			ptr = i;
		}
		if (mSpeedHistoryTx[i] > max) {
			max = mSpeedHistoryTx[i];
			ptr = i;
		}
	}
	mMaxSpeed = max;
	mMaxSpeedAge = (mSpeedHistoryPtr > ptr) ? (mSpeedHistoryPtr - ptr)
                   : (mSpeedHistoryPtr + HISTORY_SIZE - ptr);
}


void torkView::sys_calcMaxSpeed() {
	double max = 0.0;
	int ptr = sys_mSpeedHistoryPtr;
	for (int i = 0; i < HISTORY_SIZE; ++i) {
		if (sys_mSpeedHistoryRx[i] > max) {
			max = sys_mSpeedHistoryRx[i];
			ptr = i;
		}
		if (sys_mSpeedHistoryTx[i] > max) {
			max = sys_mSpeedHistoryTx[i];
			ptr = i;
		}
	}
	sys_mMaxSpeed = max;
	sys_mMaxSpeedAge = (sys_mSpeedHistoryPtr > ptr) ?
                          (sys_mSpeedHistoryPtr - ptr) :
                          (sys_mSpeedHistoryPtr + HISTORY_SIZE - ptr);
}


double torkView::calcSpeed(const double* buffer) const {
	double total = 0.0;
	for (int i = 0; i < SPEED_BUFFER_SIZE; ++i)
		total += buffer[i];
	return total/SPEED_BUFFER_SIZE;
}

double torkView::byteSpeedRx() const {
	return mSpeedHistoryRx[mSpeedHistoryPtr];
}

double torkView::byteSpeedTx() const {
	return mSpeedHistoryTx[mSpeedHistoryPtr];
}

double torkView::sys_byteSpeedRx() const {
	return sys_mSpeedHistoryRx[sys_mSpeedHistoryPtr];
}

double torkView::sys_byteSpeedTx() const {
	return sys_mSpeedHistoryTx[sys_mSpeedHistoryPtr];
}

TQString torkView::byteFormat( double num, const char* ksufix,
                              const char* msufix ) {
	const double ONE_KB = 1024.0;
	const double ONE_MB = ONE_KB*ONE_KB;
	if ( num >= ONE_MB ) 	// MB
		return TQString::number( num/(ONE_MB), 'f', 1 ) + msufix;
	else	// Kb
		return TQString::number( num/ONE_KB, 'f', 1 ) + ksufix;
}

class streamItem : public TQObject, public TQListViewItem
{
TQ_OBJECT

public:
    streamItem( DndListView *parent, const TQString &id,
                const TQString &program, const TQString &target,
                const TQString &status, const TQString &bw,
                const TQString &exit, const TQString &circuit );
    streamItem();

	enum {
		HISTORY_SIZE = 300,	// Speed history buffer size
		SPEED_BUFFER_SIZE = 10	// Speed normalization buffer size
	};

	//	Rx e Tx to bytes and packets
	unsigned long mBRx, mBTx;
	// Statistics
	unsigned long mTotalBytesRx, mTotalBytesTx;
	// Speed buffers
	double mSpeedBufferRx[SPEED_BUFFER_SIZE], mSpeedBufferTx[SPEED_BUFFER_SIZE];
	// pointer to current speed buffer position
	int mSpeedBufferPtr;

	// History buffer TODO: Make it configurable!
	double mSpeedHistoryRx[HISTORY_SIZE];
	double mSpeedHistoryTx[HISTORY_SIZE];

	int mSpeedHistoryPtr;
	double mMaxSpeed;
	int mMaxSpeedAge;

	const double* speedHistoryRx() const { return mSpeedHistoryRx; }
	const double* speedHistoryTx() const { return mSpeedHistoryTx; }
	int historyBufferSize() const { return HISTORY_SIZE; }
	const int* historyPointer() const { return &mSpeedHistoryPtr; }
	const double* maxSpeed() const { return &mMaxSpeed; }

	// calc tha max. speed stored in the history buffer
	inline void calcMaxSpeed();

	// calc the speed using a speed buffer
	inline double calcSpeed(const double* buffer) const;

	/// RX Speed in bytes per second
	inline double byteSpeedRx() const;
	/// TX Speed in bytes per second
	inline double byteSpeedTx() const;

    inline void calcBWRate(int torbrx, int torbtx, int secs);

private:


    bool dragging;

};




void streamItem::calcBWRate(int torbrx, int torbtx, int secs) {

    //Calculate Stream Tx/Rx
    unsigned int btx = (torbtx - mBTx);
    unsigned int brx = (torbrx - mBRx);
    mBRx = torbrx;
    mBTx = torbtx;

    if (++mSpeedBufferPtr >= SPEED_BUFFER_SIZE)
        mSpeedBufferPtr = 0;

    mSpeedBufferTx[mSpeedBufferPtr] = ((btx )*(1000.0f/(secs * 1000)));
    mSpeedBufferRx[mSpeedBufferPtr] = ((brx )*(1000.0f/(secs * 1000)));


    if (++mSpeedHistoryPtr >= HISTORY_SIZE)
        mSpeedHistoryPtr = 0;
    mSpeedHistoryRx[mSpeedHistoryPtr] = calcSpeed(mSpeedBufferRx);
    mSpeedHistoryTx[mSpeedHistoryPtr] = calcSpeed(mSpeedBufferTx);

    mMaxSpeedAge--;

    if (mSpeedHistoryTx[mSpeedHistoryPtr] > mMaxSpeed) {
        mMaxSpeed = mSpeedHistoryTx[mSpeedHistoryPtr];
        mMaxSpeedAge = HISTORY_SIZE;
    }
    if (mSpeedHistoryRx[mSpeedHistoryPtr] > mMaxSpeed)  {
        mMaxSpeed = mSpeedHistoryRx[mSpeedHistoryPtr];
        mMaxSpeedAge = HISTORY_SIZE;
    }
    if (mMaxSpeedAge < 1)
        calcMaxSpeed();

}

void streamItem::calcMaxSpeed() {
	double max = 0.0;
	int ptr = mSpeedHistoryPtr;
	for (int i = 0; i < HISTORY_SIZE; ++i) {
		if (mSpeedHistoryRx[i] > max) {
			max = mSpeedHistoryRx[i];
			ptr = i;
		}
		if (mSpeedHistoryTx[i] > max) {
			max = mSpeedHistoryTx[i];
			ptr = i;
		}
	}
	mMaxSpeed = max;
	mMaxSpeedAge = (mSpeedHistoryPtr > ptr) ? (mSpeedHistoryPtr - ptr)
                    : (mSpeedHistoryPtr + HISTORY_SIZE - ptr);
}



double streamItem::calcSpeed(const double* buffer) const {
	double total = 0.0;
	for (int i = 0; i < SPEED_BUFFER_SIZE; ++i)
		total += buffer[i];
	return total/SPEED_BUFFER_SIZE;
}

double streamItem::byteSpeedRx() const {
	return mSpeedHistoryRx[mSpeedHistoryPtr];
}

double streamItem::byteSpeedTx() const {
	return mSpeedHistoryTx[mSpeedHistoryPtr];
}


class circuitItem : public TQObject, public TQListViewItem
{
TQ_OBJECT

public:
    circuitItem( DndListView *parent, const TQString &id,
                 const TQString &status, const TQString &server );

//     bool acceptDrop( const TQMimeSource *mime ) const;
//     void dropped ( TQDropEvent * e );
//     void dragEntered( );


};



#endif // _TORKVIEW_H_
