#ifndef KADU_MISC_H
#define KADU_MISC_H

#include <qdatetime.h>
#include <qdialog.h>
#include <qfiledialog.h>
#include <qimage.h>
#include <qlabel.h>
#include <qstring.h>
#include <qvbox.h>

#include <time.h>

#include "status.h"

class QComboBox;
class QLineEdit;
class QListBox;
class QMenuData;
class QPopupMenu;

/*
	Zmienia ścieżkę relatywną do katalogu z ustawieniami gg
	na ścieżkę bezwzgledną uwzględniając zmienne środowiskowe
	$HOME i $CONFIG_DIR
*/
QString ggPath(const QString &subpath = QString::null);

/*
	zwraca ścieżkę do pliku f
	jeżeli drugi parametr nie jest == 0, to funkcja próbuje najpierw ustalić
	ścieżkę na podstawie argv0, które ma być równe argv[0] oraz zmiennej PATH
*/
QString dataPath(const QString &f = QString::null, const char *argv0 = 0);

QString libPath(const QString &f = QString::null);

class UserListElement;

QString cp2unicode(const unsigned char *);
QString unicode2cp(const QString &);
QString latin2unicode(const unsigned char *);
QCString unicode2latin(const QString &);
QString unicode2std(const QString &);

//zamienia kodowanie polskich znaków przekonwertowane z utf-8 przy pomocy QUrl::encode na kodowanie latin-2
QString unicodeUrl2latinUrl(const QString &buf);
//zamienia polskie znaki na format latin2 "url" (czyli do postaci %XY)
QString unicode2latinUrl(const QString &buf);

QString printDateTime(const QDateTime &datetime);
QString timestamp(time_t = 0);
QDateTime currentDateTime();
QString pwHash(const QString &text);
QString translateLanguage(const QApplication *application, const QString &locale, const bool l2n);

void openWebBrowser(const QString &link);
void openMailClient(const QString &mail);
void openGGChat(const QString &gg);

QString versionToName(const unsigned int version);

void stringHeapSort(QStringList &c);
QStringList toStringList(const QString &e1, const QString &e2=QString(), const QString &e3=QString(), const QString &e4=QString(), const QString &e5=QString());

void saveGeometry(const QWidget *w, const QString &section, const QString &name);
void loadGeometry(QWidget *w, const QString &section, const QString &name, int defaultX, int defaultY, int defaultWidth, int defaultHeight);

int showPopupMenu(QPopupMenu *menu);

//usuwa znaki nowego wiersza, tagi htmla (wszystko co da się dopasować jako <.*>)
QString toPlainText(const QString &text);

extern QFont *defaultFont;
extern QFontInfo *defaultFontInfo;

extern QTextCodec *codec_cp1250;
extern QTextCodec *codec_latin2;

class ChooseDescription : public QDialog
{
	Q_OBJECT

	static ChooseDescription *Dialog;

	QPushButton *OkButton;
	QComboBox *Description;
	QLabel *AvailableChars;

	UserStatus Status;

private slots:
	void okPressed();
	void cancelPressed();
	void updateAvailableChars(const QString &);

public:
	static void show(const UserStatus &status, const QPoint &position);

	ChooseDescription(QWidget *parent = 0, const char *name = 0);
	virtual ~ChooseDescription();

	void setStatus(const UserStatus &status);
	void setPosition(const QPoint &position);

};

class OpenChatWith : public QVBox
{
	Q_OBJECT

	QComboBox *c_text;
	QComboBox *c_protocol;

private slots:
	void inputAccepted();

protected:
	virtual void keyPressEvent(QKeyEvent *e);

public:
	OpenChatWith(QWidget *parent = 0, const char *name = 0);
	virtual ~OpenChatWith();

};

class ImageWidget : public QWidget
{
//	Q_OBJECT

	private:
		QImage Image;

	protected:
		virtual void paintEvent(QPaintEvent *e);

	public:
		ImageWidget(QWidget *parent);
		ImageWidget(QWidget *parent,const QByteArray &image);
		void setImage(const QByteArray &image);
		void setImage(const QPixmap &image);
};

class TokenDialog : public QDialog
{
	Q_OBJECT

	public:
		TokenDialog(QPixmap tokenImage, QDialog *parent = 0, const char *name = 0);
		void getValue(QString &tokenValue);

	private:
		QLineEdit *tokenedit;
};

/**
	klasa rozwiazujaca problem z powiadomieniem
	o utworzeniu nowej instancji danej klasy.
	umieszczamy w klasie publiczna statyczna
	zmienna createNotifier klasy CreateNotifier
	do ktorej mogą się podłączać pozostałe cześci kodu.
	przed wyjściem z konstruktora wywołujemy metodę:
	createNotifier.notify(this);
**/
class CreateNotifier : public QObject
{
	Q_OBJECT

	public:
		void notify(QObject* new_object);

	signals:
		void objectCreated(QObject* new_object);
};


class PixmapPreview : public QLabel, public QFilePreview
{
	public:
		PixmapPreview();
		void previewUrl(const QUrl& url);
};

class ImageDialog : public QFileDialog
{
	public:
		ImageDialog(QWidget* parent);
};

class QLabel;
class QSimpleRichText;

/*
	Class for helping Qt do a proper layout of labels which use alignment flag Qt::WordBreak
	see: http://www.trolltech.com/developer/tasktracker.html?method=entry&id=103552 and
		http://doc.trolltech.com/qq/qq04-height-for-width.html
*/
class LayoutHelper
{
	public:
		LayoutHelper();
		~LayoutHelper();
		void addLabel(QLabel *label);
		void textChanged(QLabel *label);
		void resizeLabels();
	private:
		QValueList<QLabel*> labels;
		QValueList<QSimpleRichText*> riches;

};

QValueList<int> toIntList(const QValueList<QVariant> &in);
QValueList<QVariant> toVariantList(const QValueList<int> &in);

/*
	zastępstwo dla arga w QString, które podmienia kolejne %[1-4] w miejscu

	w QStringu efektem:
		QString("%1 odstęp %2").arg("pierwszy %1 tekst").arg("drugi tekst") jest "pierwszy drugi tekst tekst odstęp %2"
	a chcielibyśmy żeby było
		"pierwszy %1 tekst odstęp drugi tekst"
	co robi właśnie ta funkcja
*/
QString narg(const QString &s, const QString &arg1, const QString &arg2,
				const QString &arg3=QString(), const QString &arg4=QString());

QString narg(const QString &s, const QString &arg1, const QString &arg2,
				const QString &arg3, const QString &arg4,
				const QString &arg5, const QString &arg6=QString(),
				const QString &arg7=QString(),const QString &arg8=QString(),
				const QString &arg9=QString());

/**
	uogólniony narg(const QString&, const QString &, const QString &, const QString &, const QString &)
	na większą liczbę parametrów
	count musi być <=9
	tab - tablica count wskaźników do QString
**/
QString narg(const QString &s, const QString **tab, int count);

void printBacktrace(const QString &header = QString::null);

// definiuje nową zmienną v o takim samym typie jak x jednocześnie inicjując ją wartością x
#define VAR(v,x)	__typeof(x) v=x

// szybsza w zapisaniu pętla for
#define FOREACH(i,c) for(VAR(i, (c).begin()); i!=(c).end(); ++i)

#define CONST_FOREACH(i,c) for(VAR(i, (c).constBegin()), _kadu__##i##__end = (c).constEnd(); i!=_kadu__##i##__end; ++i)

// private
extern long long int startTime, beforeExecTime, endingTime, exitingTime;
extern bool measureTime;

extern const char *detailed_version;

#endif
