////////////////////////////////////////////////////////////////////////////////
// ArchiveViewer.h
// Screen for viewing archives
// Copyright Bjoern Ganster
// Developed since 2007
////////////////////////////////////////////////////////////////////////////////

#pragma once

#include "Archive.h"
#include "Audio.h"
#include "MemoryBlock.h"
#include "MechWarriorIIPRJ.h"
#include "Sound.h"
#include "Texture.h"
#include "Mesh.h"

#include "GLButton.h"
#include "GLLabel.h"
#include "GLTableView.h"
#include "GLTableView.h"
#include "GLWindowContainer.h"

const int MW2PRJ_upDirButtonID = 4;
const int MW2PRJ_TableID = 5;
const int MW2PRJ_ExitButtonID = 64;

////////////////////////////////////////////////////////////////////////////////

class ArchiveViewer: public GLWindowContainer, public GLTableViewDataSource, public AudioProvider  {
public:
	// Constructor
	ArchiveViewer(int _left = 0, int _top = 0, int _width = 0, int _height = 0);

	// Destructor
	~ArchiveViewer() OVERRIDE;

	// Set up archive viewer to view an archive
	bool exploreArchive(const PathChar* FN);

	// Set up archive viewer to view a single file as a fake archive
	bool exploreSingleFile(const PathChar* FN);

	// View external file
	void viewFile();

	// View external file
	bool viewDir(const PathChar* fileName);

	// TableView implementation: get number of rows and columns
	void getDimensions (size_t senderID, size_t& rowCount, size_t& colCount) OVERRIDE;

	// TableView implementation: Get string for a cell
	bool getString (size_t senderID, int row, int col, BGCPString& str) OVERRIDE;

	// Receive messages
	void receiveMessage (VirtualClass* sender, int MessageType, VirtualClass* data = nullptr);

	// Render
	void render(int x, int y, int w, int h) OVERRIDE;

	// Called to set new layout
	void setGeometry (int left, int top, int newWidth, int newHeight);

	// Keyboard event handler
	void keypressed (BGKey key, bool shiftHeld, bool ctrlHeld, bool down, bool repeat);

	// Provide audio via SDL callback
	void provideAudio(void* userdata, Uint8* stream, int len) OVERRIDE;

	// View MW3 terrain (stored in a world node in gamez.zbd)
	void viewMW3Terrain();
private:
	GLLabel* label;
	MWArchive* mwArchive;
	GLTableView* PRJTable;
	GLButton* upDirButton;
	Texture texture;
	Mesh* mesh;
	Point3D meshCenter;
	double viewDist;
	double zoom;
	MemoryBlock clipBlock;
	int frame;
	Palette mPal;

	// Sound data
	SDL_mutex* mSoundMutex;
	size_t soundOffset;
	std::vector<Sound*> mQueuedSounds;

	int mode; // 0: ignore, 1: decode SHP frames from clipBlock

	void unpackPrj();

	// Request context menu
	void showContextMenu(VirtualClass* sender, int x, int y);

	// View file inside a PRJ file
	void getSelectedFileName(BGCPString& FN);
	bool getSelectedFile(MemoryBlock& block);

	// Export files from PRJ
	void exportBWD(bool recursive);
	void exportXEL();
	void exportTEX();
	void exportEFA(int format);

	// Decode CD-DA to wav
	void exportCddaAsWave();

	// Import a level from a BWD
	void importLevel();

	// Import a scene graph from a gamez.zbd
	void importGameZNodes();

	// Replace a WTB file inside a PRJ with an external OBJ file
	void replaceWTBwithOBJ();

	// Export filters
	void exportWTB();
	void exportSFL();
	void exportSHP(const Palette& pal);

	void viewMesh(const MemoryBlock* mb, const PathChar* fileName);
	void viewObj(const PathChar* fileName);
	void showMech(const MemoryBlock* mb, const PathChar* fileName);
	bool playWAV(const MemoryBlock* mb);

	void displayMsg (const BGCPString& msg);

	void exportFntAsBmp();

	// Add sound to queue
	void queueSound(const Sound& sound);

	// Decode and view a mesh from a MW3 gameZ.ZBD
	void viewGameZMesh(size_t fileNum, int subtype);

	void exportMW3GameZMeshAsObj();

	// Export MW3 zreader archive as XML ...
	void exportMW3ZReaderAsXml();
	void exportMW3ZReaderAsXmlRec(size_t& offset, XMLTreeIterator& xmlIter);

	void exportMW3_555AsBmp();
};
