// $Id: IGrfPacker 45 2005-06-10 00:07:16Z Rasqual $
//Copyright (c) 2004 Rasqual Twilight

#if !defined(__IGRFPACKER__)
#define __IGRFPACKER__

#include  <list>
#include  "grfexceptions.h"
#include  "utf16.h"
#include  "ICancelPoller"
#include  "IGrfEntry"


/**
    IGrfPacker interface definition.
    To use this class, instantiate an object of a subclass and perform add operations
    by calling the methods.
    When the file is ready for writing, call the foo() method.
    Because we apply the Strategy pattern, you must supply the functions that will
    implement a given interface for the following operations:
      - Wrapping file opening and closing
      - Wrapping file I/O
    For example, you could implement this using stdio, iostream, Win32 api...
**/
class IGrfPacker {
public:
	IGrfPacker() {}
	virtual ~IGrfPacker() {}

public:
	/**
		Sets a callback object instanciating ICancelPoller or a derived class
		that checks for cancel requests.
		Default never cancels an operation.
	**/
	virtual void SetCancelStatePoller(ICancelPoller *) = 0;
	
	/**
		Gets the callback object instanciating ICancelPoller or a derived class
		that checks for cancel requests.
	**/
	virtual ICancelPoller *GetCancelStatePoller() const = 0;

	/**
		Adds an entry to the grf file, while preserving the order of insertion.
		If an entry with the <<same characteristics>> (e.g. same name) is matched,
		the behavior is implementation-dependant. If the implementation does not
		allow duplicates, the previous entry is first removed from the current set
		and used for the return value, then the new entry is inserted at the end.
		Caller is responsible for management of the memory pointed by pEntry.
		Throws: GPNullPointerException if pEntry is 0
		Returns the value of a previous entry with the same name, if applicable, 0 otherwise.
	**/
	virtual IGrfEntry * AddEntry(IGrfEntry *pEntry)
	  throw ( GPNullPointerException, GPCancelOperationException ) = 0;

	/**
		Finds and removes an entry from the grf file.
		If the pointed address does not belong to the current entries, the function fails silently.
		Caller is responsible for management of the memory pointed by pEntry.
		Throws: GPNullPointerException if pEntry is 0
		Throws: GPUnsupportedOperationException if the implementation does not allow removing entries
	**/
	virtual void RemoveEntry(const IGrfEntry *pEntry)
	  throw ( GPNullPointerException, GPUnsupportedOperationException ) = 0;

	/**
		Opens a file descriptor for writing, truncating it if it already exists, and
		writes grf contents into it.
		Returns 0 if all went well, non-0 otherwise

		Throws: GPNullPointerException if utf16le_encoded_filepath is 0
		Throws: GPInvalidSequenceException if the utf16le_encoded_filepath
		  has an invalid value (bad sequences, etc.)
		Throws: GPIoException if a file I/O operation has failed. The errno class member
		  designates a error code set by the user-supplied class responsible for doing the operation.
		Throws: GPUnlogicalException if utf16le_encoded_filepath already exists and is not or does not point to a regular file.
		Throws: GPIllegalStateException if an operation was aborted due to an illegal state
		Throws: GPUnsupportedOperationException if unable to open a file with such a name
	**/
	virtual int PackFile(const UTF16_t utf16le_encoded_filepath[])
	  throw ( GPNullPointerException, GPInvalidSequenceException, GPIoException, GPUnlogicalException, GPIllegalStateException, GPUnsupportedOperationException ) = 0;

	/**
		Tests whether a grf with the provided version can be produced.
	**/
	virtual bool IsSupportedVersion(uint16_t) const = 0;
	/**
		Returns the smallest version that can be produced with the packer.
	**/
	virtual uint16_t GetMinVersion() const = 0;
	/**
		Returns the greatest version that can be produced with the packer.
	**/
	virtual uint16_t GetMaxVersion() const = 0;
	/**
		Returns a list of versions that can be produced with the packer.
	**/
	virtual std::list<uint16_t> GetSupportedVersions() const = 0;
	/**
		Retrieve the version currently being used for packing.
	**/
	virtual uint16_t GetVersion() const = 0;
	/**
		Instruct the packer to work with a particular version.
		By default, the packer is set to work with the most compatible version available.
		You may change the version anytime, it will be applied when calling PackFile()
		Returns the previously set version.
		Throws: GPInvalidParameterException if the version is not supported.
	**/
	virtual uint16_t SetVersion(uint16_t)
	  throw ( GPInvalidParameterException ) = 0;

private:
	IGrfPacker(const IGrfPacker&);
	IGrfPacker &operator=(const IGrfPacker&);
};

#endif  // !defined(__IGRFPACKER__)
