#ifndef _FILEINFO_H_
#define _FILEINFO_H_

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <qfileinf.h>
#include <qstring.h>
#include <qpixmap.h>
#include <qdatetm.h>
#include <qlist.h>
#include <qdir.h>

#define	READ_OK		1
#define	WRITE_OK	2
#define	EXEC_OK		4

/*#define	STAT_IFDIR	0x8000
#define	STAT_IFLNK	0x4000
#define	STAT_IFREG	0x2000
#define	STAT_IFIFO	0x1000
#define	STAT_IFBLK	0x0800
#define	STAT_IFCHR	0x0400

#define	STAT_IRUSR	0x0100
#define	STAT_IWUSR	0x0080
#define	STAT_IXUSR	0x0040
#define	STAT_IRGRP	0x0020
#define	STAT_IWGRP	0x0010
#define	STAT_IXGRP	0x0008
#define	STAT_IROTH	0x0004
#define	STAT_IWOTH	0x0002
#define	STAT_IXOTH	0x0001*/

#include "kmime.h"		// defined in "kmime.h"

class FileInfo
{
public:
	FileInfo(QFileInfo *);	// For QDir outputs
	FileInfo(const char *,int);
//	FileInfo(const char *, bool);	// For FTP outputs
//	FileInfo(const char *, char); // For normal file output -- with readdir()
	FileInfo(const FileInfo& kfi);
	void parseFileString(const char *str);
	void parseFTPString(const char *str, bool Unix);
	void parseTarString(const char *str);
	void parseZipString(const char *str);
	void parseRpmString(const char *str);
	~FileInfo();

	void setIcons(QPixmap *icon, QPixmap *miniIcon = 0) { Icon = icon; MiniIcon = miniIcon;}
	QPixmap* icon() { return Icon;}
	QPixmap* miniIcon() { return MiniIcon;}
// OLE
	QPixmap* miniImage(){ return &MiniImage;}
	void setMiniImage(QPixmap miniImage) {MiniImage=miniImage;}
// OLE
	void setPath(const char *path) { Path = path;}
	void setOpenApplication(const char *app) { OpenAppl = app;}
	const char* openApplication() { return OpenAppl.data();}
	void setDescription(const char *desc) { Desc = desc;}
	const char* description() { return Desc.data();}
	void setIndex(int ind) { Index = ind;}
	int index() { return Index;}
	void setMimeType(KMimeExtension *mime) { MimeType = mime;}
	KMimeExtension* mimeType() { return MimeType;}

	QString fileName() const { return Name;}
	void setFileName(const char *name) { Name = name;}
	const char* filePath() const { return Path.data();}
	QString absFilePath() const { return Path;}
	QString extension() const;
	QString lastExtension() const;
	QString dirPath() const;
	bool isReadable() const;
	bool isWritable() const { return (UserMode & WRITE_OK);}
	bool isExecutable() const { return (UserMode & EXEC_OK);}
	bool isFile() const { return S_ISREG(RealMode);}
	bool isDir() const { return S_ISDIR(RealMode);}
	bool isFifo() const { return S_ISFIFO(RealMode);}
	bool isBlock() const { return S_ISBLK(RealMode);}
	bool isSymLink() const { return S_ISLNK(Mode);}
	bool isChr() const { return S_ISCHR(RealMode);}
	bool isSocket() const { return S_ISSOCK(RealMode);}
	QString readLink() const { return LinkPath;}
	const char* owner() const { return Owner.data();}
	const char* group() const { return Group.data();}
	uint size() const { return Size;}
	QDateTime lastModified() const { return Date;}
	QString permissions() { return Permissions;}
	bool permissions(int m) { return ((RealMode & 0x01FF) & m);}
	bool isCutted() { return Cutted;}
	void setCutted(bool val) { Cutted = val;}
	int numberOfLinks() { return nLinks;}
	void setNumberOfLinks(int n) { nLinks = n;}
	bool isLocal() { return Local;}
// OLE 1
	void markAsYetSearchedForMiniImage() { YetSearchedForMiniImage=true;}
	bool yetSearchedForMiniImage() { return YetSearchedForMiniImage;}
// OLE 1

private:
	QString	Name;
	QString	Path;			// Need to be set when created from string
	QString	Owner;
	QString	Group;
	mode_t	Mode;
	mode_t	RealMode;
	int	UserMode;
	uint	Size;
	QDateTime	Date;
	QString	LinkPath;
	QPixmap	*Icon;			// To be set by applications
	QPixmap	*MiniIcon;
	QString	Desc;
	QString	OpenAppl;
	int	Index;
	QString	Permissions;
	KMimeExtension	*MimeType;
	bool	Cutted;
	int	nLinks;
	bool	Local;
// OLE
	QPixmap MiniImage;
	bool    YetSearchedForMiniImage;
// OLE
};

typedef	QList<FileInfo>		FileInfoListBase;
typedef	QListIterator<FileInfo>	FileInfoListIterator;

enum SortType { byName, bySize, byType, byTime};

class FileInfoList : public FileInfoListBase
{
public:
	FileInfoList(int sort = byName) : FileInfoListBase(), SortS(sort) {}
	void setSorting(int sort) { SortS = sort;}
	void copy(const FileInfoList *list)
		{
			FileInfo	*item;
			clear();
			FileInfoListIterator	it(*list);
			for ( ; it.current(); ++it) {
				item = new FileInfo(*it.current());
				append(item);
			}
		}

protected:
#define	IT1	((FileInfo*)item1)
#define	IT2	((FileInfo*)item2)
	virtual int compareItems(GCI item1, GCI item2)
		{
			int	tmp;
			if (IT1->isDir()) {
				if (IT2->isDir())
					switch (SortS) {
					   case byName : return strcmp(IT1->fileName().data(),IT2->fileName().data());
					   case bySize : if (IT1->size() < IT2->size()) return -1;
							 else if (IT1->size() > IT2->size()) return 1;
							 else return 0;
					   case byTime : if (IT1->lastModified() < IT2->lastModified()) return -1;
					     		 else if (IT1->lastModified() > IT2->lastModified()) return 1;
					     		 else return 0;
					   case byType : if ((tmp = strcmp(IT1->description(),IT2->description())) == 0) return strcmp(IT1->fileName().data(),IT2->fileName().data());
							 else return tmp;
					   default : return strcmp(IT1->fileName().data(),IT2->fileName().data());
					}
				else return -1;
			}
			else {
				if (!IT2->isDir())
					switch (SortS) {
					   case byName : return strcmp(IT1->fileName().data(),IT2->fileName().data());
					   case bySize : if (IT1->size() < IT2->size()) return -1;
							 else if (IT1->size() > IT2->size()) return 1;
							 else return 0;
					   case byTime : if (IT1->lastModified() < IT2->lastModified()) return -1;
					     		 else if (IT1->lastModified() > IT2->lastModified()) return 1;
					     		 else return 0;
					   case byType : if ((tmp = strcmp(IT1->description(),IT2->description())) == 0) return strcmp(IT1->fileName().data(),IT2->fileName().data());
							 else return tmp;
					   default : return strcmp(IT1->fileName().data(),IT2->fileName().data());
					}
				else return 1;
			}
		}
#undef	IT1
#undef	IT2

private:
	int	SortS;
};

#endif
