#ifndef __MILETOS_XFPK_H__
#define __MILETOS_XFPK_H__

//
// Libmiletos
//
// Copyright (C) Lauris Kaplinski 2007-2009
//

#include <string>
#include <vector>
#include <map>

#include <miletos/types.h>
#include <miletos/filesystem.h>
#include <miletos/uri.h>

namespace Miletos {

namespace Xfpk {

class FileData {
private:
	unsigned int valid;
	std::string tblname;
	std::string dataname;

	struct FileEntry {
		u32 tag;
		std::string name;
		size_t start;
		size_t length;
	};
	std::vector<FileEntry> entries;
	std::map<std::string, int> map;

	// Helpers
	void readTable (const unsigned char *tdata, size_t tsize, const unsigned char *cdata, size_t csize);
	bool isCompressed (int idx);
public:
	// Constructor
	FileData (const char *tblname, const char *dataname);
	// FileData (const unsigned char *tdata, size_t tsize, const unsigned char *pxdata, size_t pxsize);

	// Access
	bool isValid (void) const { return valid != 0; }
	int getNumFiles (void) { return (int) entries.size (); }
	const char *getFileName (int idx);
	size_t getFileSize (int idx);
	const unsigned char *getFileData (int idx, size_t *size);
	Miletos::u32 getFileTag (int idx);
	int lookupFileIdx (const char *name) { if (map.find (name) == map.end ()) return -1; return map[std::string(name)]; }

	// Static helpers
	static bool isTable (const char *filename);
	static u16 getU16LE (const unsigned char *c) { return (u16) c[0] | ((u16) c[1] << 8); }
	static u32 getU32LE (const unsigned char *c) { return (u32) c[0] | ((u32) c[1] << 8) | ((u32) c[2] << 16) | ((u32) c[3] << 24); }
	static unsigned char *unpack_a67f54cb (const unsigned char *cdata, size_t csize, size_t& dsize);
};

class FileHandler : public FileSystem::HandlerFileList {
private:
	FileData data;

	// Handler implementation
	// Test whether current handler has dir (relative to root)
	virtual bool hasDir (const char *name);

	// Set current reading directory to given value (or unset if there is no such dir)
	virtual bool loadDir (const char *name);
	// Return the number of files in reading dir
	virtual int getNumFiles (void);
	// Return the name of file in reading dir
	virtual const char *getFileName (int idx);
	// Return the size of file in reading dir
	virtual size_t getFileSize (int idx);
	// Return the number of subdirectories in reading dir
	virtual int getNumSubDirs (void);
	// Return the name of subdirectory in reading dir
	virtual const char *getSubDirName (int idx);

	// HandlerFileList implementation
	virtual void addFileMapping (Entry *entry);
public:
	// Constructor
	FileHandler (const char *tblname, const char *dataname);
};

class URLHandler : public URI::URLHandler {
private:
	std::vector<FileSystem::Handler *> handlers;

	URLHandler (const char *location);
	virtual ~URLHandler (void);

	// URLHandler implementation
	virtual const unsigned char *mmapDataRelative (const char *name, size_t *size);
	virtual void munmapData (const unsigned char *data);
public:
	// Static constructor
	static URI::URLHandler *newURLHandler (const char *url);
};

}; // Namespace Xfpk

}; // Namespace Miletos

#endif
